Подтвердить что ты не робот

Так много скобок в стандартных заголовках gcc

Почему постоянные выражения в заголовочных файлах GCC окружены круглыми скобками, например?

#define INTMAX_MIN (-9223372036854775807LL)
#define INTMAX_MAX (9223372036854775807LL)

Какая разница, если я опускаю круглые скобки, таким образом?

#define INTMAX_MIN -9223372036854775807LL
#define INTMAX_MAX 9223372036854775807LL

И почему существует суффикс 'L'? Было бы так же, если бы я написал следующее?

#define INTMAX_MIN -9223372036854775807
#define INTMAX_MAX 9223372036854775807

Есть ли реальная полезность или это всегда одно и то же?

Я знаю, что "L" длится долго, и я также хорошо осведомлен о важности скобок в макросах C; Я спрашиваю об этом ради любопытства.

4b9b3361

Ответ 1

Если вы написали

a = 7 INTMAX_MIN;

вы ожидаете получить синтаксическую ошибку, потому что на первый взгляд это будет незаконным выражением. И он будет, потому что он расширяется до

a = 7 (-9223372036854775807LL);

который действительно дает вам синтаксическую ошибку. Но без круглых скобок он будет расширяться до:

a = 7 -9223372036854775807LL;

который не дает вам ошибки, несмотря на то, что вы явно не то, что вы намеревались.

В более общем плане, все они определяют, что дает расширения для вещей, которые выглядят как идентификаторы. В арифметическом выражении идентификатор является "основным выражением", но -9223372036854775807LL не является. Однако выражение в скобках является "основным выражением".

И это настоящая причина. Так что макрос расширяет то, что выглядит как первичное выражение, на то, что является основным выражением. Вы никогда не будете удивлены тем, что произойдет. В программировании неожиданность обычно плохая.

Обычно это не имеет значения, но люди, которые написали определения, не хотят, чтобы они обычно работали. Они хотят, чтобы они всегда работали.

Конечный LL отмечает этот целочисленный литерал по типу long long, который обычно (и в этом случае - 64 бит). Без суффикса LL литерал может быть интерпретирован как int, long int или long long int, в зависимости от того, что первым поддерживает 64-битные значения. Гвоздь вниз типа может быть столь же важным, как пригвождение вниз.

Ответ 2

Хорошая практика поместить скобки в макрос с целочисленной константой и унарным оператором вроде этого:

#define BLA (-1)

поскольку унарные операторы (- здесь) не имеют наивысшего приоритета в C. Операторы Postfix имеют более высокий приоритет, чем унарные операторы. Помните, что C не имеет отрицательных констант, например -1 - это константное выражение, которому предшествует оператор tary > t21 > .

В качестве стороннего PC-Lint предлагаются скобки в таких макросах:

(правило 973): скобки #define N (-1) Унарный оператор в макросе "Символ" не в скобках - Унарный оператор, появляющийся в макросе, подобном выражению, оказался не в скобках. Для Пример:

#define N -1

Пользователь может предпочесть заключить в скобки такие вещи, как:

#define N (-1)

Ответ 3

Этот ответ пытается показать, почему нужен LL. (Это непросто.)
Другие ответы показали, почему нужны скобки.

Пусть код три макроса, все являются десятичными константами.

#define MAXILL (9223372036854775807LL)
#define MAXIL  (9223372036854775807L)
#define MAXI   (9223372036854775807)

Даже если MAXI не имеет суффикса, это не делает его типом int. MAXI будет иметь первый тип, в который он входит, либо int, long, long long, либо расширенный целочисленный тип.

Даже если MAXIL имеет суффикс L, он будет иметь первый тип, в который он входит, либо long, long long, либо расширенный целочисленный тип.

Даже если MAXILL имеет суффикс LL, он будет иметь первый тип, в который он вписывается, либо long long, либо расширенный целочисленный тип.

В каждом случае макросы имеют одинаковое значение, но потенциально разные типы.

См. C11dr §6.4.4.1 5 для определения типа.


Попробуйте распечатать их, а int и long - 32-битные, а long long и intmax_t - 64.

printf("I   %d %d %d",       MAXI, MAXIL, MAXILL);    //Error: type mismatch
printf("LI  %ld %ld %ld",    MAXI, MAXIL, MAXILL);    //Error: type mismatch
printf("LLI %lld %lld %lld", MAXI, MAXIL, MAXILL);    //Ok

Все три в последней строке верны, так как все три макроса long long, предыдущие имеют неправильные совпадения между спецификатором формата и номером.

Если у нас есть int 32-разрядный и long, long long и intmax_t равны 64, то верно следующее.

printf("LI  %ld %ld",    MAXI, MAXIL);
printf("LLI %lld", MAXILL);

Максимальный тип целочисленного ширины имеет спецификатор формата "%" PRIdMAX. Этот макрос не может расширяться до "%ld" и "%lld" для размещения MAXI, MAXIL, MAXILL. Он имеет значение "%lld", а числа, относящиеся к intmax_t, должны иметь один и тот же тип. В этом случае следует использовать long long и использовать только форму MAXILL.


Другие реализации могут иметь расширенный целочисленный тип (например, int128_t), и в этом случае может использоваться суффикс, специфичный для реализации, или какой-либо механизм.