Как стать автором
Обновить

Небольшая или большая интроспективная программа на C/C++

Время на прочтение1 мин
Количество просмотров2.7K
Под Хабракатом небольшой этюд позволяющий писать маленькие или большие приложения, которые содержат в себе свой же код и выглядят при этом почти адекватно.

#include <stdio.h>
#define REPEAT(...) #__VA_ARGS__;__VA_ARGS__
char * ref = REPEAT(
int main()
{
	printf("#include <stdio.h>\n"
		   "#define REPEAT(...) #__VA_ARGS__;__VA_ARGS__\n"
		   "char * ref = REPEAT(%s)", ref);
	return 0;
}
)

Как видно из исходника, явно списать код нужно только из «шапки», потому что все что находится в REPEAT-блоке будет автоматически застринговано и сохранено.
Сам макрос REPEAT устроен следующим образом: он принимает переменное число аргументов (чтоб не боятся запятых), затем «стрингует» то что ему передали, а затем еще раз повторяет то что ему передали, но на этот раз без кавычек (чтоб сохранить функционал).
Вот что получается после препроцессинга:
g++ -E main.cpp

char * ref = 
"int main()"
"{"
"    printf(\"#include <stdio.h>\\n\"" 
"           \"#define REPEAT(...) #__VA_ARGS__;__VA_ARGS__\\n\"" 
"           \"char * ref = REPEAT(%s)\", ref);"
"    return 0;" 
"}";
int main() 
{ 
    printf("#include <stdio.h>\n" 
           "#define REPEAT(...) #__VA_ARGS__;__VA_ARGS__\n" 
           "char * ref = REPEAT(%s)", ref); 
    return 0; 
}

Признаться честно, я код изменил и привел в читаемый вид, потому что препроцессор почти все лепит в одну строчку. Тем не менее кроме переносов и лишних кавычек все на своих местах.
После запуска в stdout будет выведен функционально-идентичный исходник. Оформление только слегка помнется.

PS #include можно внести в REPEAT-блок, тогда его можно будет не писать явно в строке.
Теги:
Хабы:
Всего голосов 33: ↑28 и ↓5+23
Комментарии12

Публикации