Стринг #a в определения, почему это плохо - PullRequest
4 голосов
/ 02 февраля 2011
#include <stdio.h>
#define print_int(a) printf("%s : %d\n",#a,(a))
int main(void) {
    int y = 10;
    print_int(y);
    return 0;
}

Я беру урок, и меня попросили объяснить, почему это плохо ... Так что, я думаю, проблема в том, чтобы пометить строку #a. Это работает, так почему это опасно?

Ответы [ 3 ]

3 голосов
/ 02 февраля 2011

потому что он обходит безопасность типа.Что происходит, когда кто-то ненавидит вас и уходит print_int("5412");

#include <stdio.h>
#define print_int(a) printf("%s : %d\n",#a,(a))
int main(void) {
    print_int("1123123");
    return 0;
}

вывод

$ gcc test.c 
test.c: In function ‘main’:
test.c:4: warning: format ‘%d’ expects type ‘int’, but argument 3 has type ‘char *’
$ ./a.out 
"1123123" : 3870
2 голосов
/ 02 февраля 2011

Я не думаю, что это плохо. Оператор stringtize очень полезен для написания макросов, таких как утверждения:

#define assert(x) do { if (!(x)) { printf("assert failed: %s\n", #x); } } while (0)

Вы злоупотребляете любой полезной функцией. Однажды у меня появилась блестящая идея «упростить» атомы Qt, написав:

#define ATOM(x)  (((#x)[0] << 24) | ((#x)[1] << 16) | ...

Так что вы можете сказать ATOM(MPEG) и получить ('M' << 24 | 'P' << 16 | ...). На самом деле, он работал достаточно хорошо, чтобы gcc мог получать целочисленные константы из него ... Иногда ... Теперь это было зло!

1 голос
/ 02 февраля 2011

Заявления препроцессора обычно считаются злыми. Плохие вещи произойдут, когда я скажу:

int a = 15;
print_int(a++);
...