какая польза от 'u' с целыми числами - PullRequest
0 голосов
/ 20 сентября 2018

Код здесь, чтобы проверить, является ли ввод 'x'.Что это значит, когда это 23u, почему мы не можем просто написать 23.

# define IS_X(a) (((unsigned)a | 32) - 97 == 23u)

Ответы [ 3 ]

0 голосов
/ 20 сентября 2018

Как указывают chux и Jonathan Leffler, результат ((unsigned)a | 32) - 97 не подписан.Возможно, что программист использовал компилятор с очень строгими уровнями предупреждения, который жаловался на сравнение, смешивающее неподписанные и подписанные значения.Принудительный тип unsigned для второго операнда 23 с суффиксом u мог бы убрать это предупреждение.

Макрос определенно подозрительный: в расширении a следует заключить в скобки:

#define IS_X(a) (((unsigned)(a) | 32) - 97 == 23u)

Макрос мог бы быть написан ((a) == 'x' || (a) == 'X'), но a будет оцениваться дважды в большинстве случаев, чего программист хотел избежать.

Поскольку этот макрос работает только для ASCII, я удивляюсь, почему не была использована эта гораздо более простая альтернатива:

#define IS_X(a)  (((a) | 32) == 'x')
0 голосов
/ 20 сентября 2018

В приведенном вами примере каждое число преобразуется в unsigned int из-за распространения unsigned из-за обычных правил арифметического преобразования;поэтому явно указывать, что 23 является беззнаковым, не нужно и, возможно, уродливее.

Суффикс 'u' к целым числам используется редко.Есть две причины, по которым я могу использовать его.

1) Если вы выполняете несколько операций только с константами, иногда явное поведение без знака является именно тем, что вам нужно.Возьмем, к примеру, unsigned int x = 524289 * 4096; Если предположить, что 32-битные целочисленные значения вычислимы переполнят подписанную версию, что является неопределенным поведением, но если мы изменим ее таким образом unsigned int x = 524289u * 4096u;, она будет отлично вписываться в unsigned int.Его поведение также всегда определяется.Мы могли бы просто привести одно из значений, но я бы сказал, что это понятнее.

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

unsigned x = 3;
/* Do stuff */
if (x > 2) // Comparison of signed and unsigned integers
{
    /* Do something */
}

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

int roundup16 (int x)
{
    return ((x - 1) | 0xf) + 1;
}

, который возвращает x, округленное до следующего кратного 16.

0 голосов
/ 20 сентября 2018

что такое использование 'u' с целыми числами

с целочисленной константой , 'u' и 'U', обеспечивающей постоянную unsigned(или unsigned long, unsigned long long, когда большой).


Что это значит, когда сейчас 23u,

# define IS_X(a) (((unsigned)a | 32) - 97 == 23u)

u составляет 23unsigned int 23, а не signed int 23.Таким образом, сравнение будет выполнено как минимум в unsigned математике.

Тем не менее, в левой части ((unsigned)a | 32) - 97 результат равен unsigned, поэтому сравнение в любом случае было бы unsigned. @ Jonathan Leffler

Некоторые компиляторы / программы проверки кода предупреждают о сравнении unsigned с int.Используя u, обе стороны имеют одинаковый тип и выводят такие предупреждения.

То, что компилятор должен предупреждать с помощью 23 - это отдельная проблема.

почему мы не можем просто написать 23.

Кодможет использовать 23 и рискнуть излишне педантичным предупреждением, отмеченным выше.


С точки зрения макроса, хорошая практика кодирования - () использование каждого параметра:

// # define IS_X(a) (((unsigned)a | 32) - 97 == 23u)
//                          v-v
#define IS_X(a) (((unsigned)(a) | 32) - 97 == 23u)
...