Печать объявленного значения char в C

Я понимаю, что переменная символа выполняется от (подписанного) -128 до 127 и (без знака) от 0 до 255

char x; x = 128; printf("%d\n", x); 

Но как это работает? Почему я получаю -128 для x ?

printf – это вариационная функция, предоставляющая только точный тип для первого аргумента.
Это означает, что поощрения по умолчанию применяются к следующим аргументам, поэтому все целые числа ранга меньше, чем int , продвигаются до int или unsigned int , а все плавающие значения ранга меньшего double повышаются до double .

Если ваша реализация имеет CHAR_BIT из 8, и простой char подписан, и у вас есть обязательная реализация с добавлением 2s, вы, таким образом, получаете

128 (буквальный) до -128 ( char / signed char ) до -128 ( int ), напечатанный как int => -128

Если все перечисленное условие, но обязательное выполнение дополнений 2s выполнено, вы получаете сигнал или определенное значение, определенное для реализации.

В противном случае вы получите вывод из 128, потому что 128 вписывается в char / unsigned char .

Стандартная цитата для случая 2 (Спасибо Мэтту за то, что он раскопал правильную ссылку ):

6.3.1.3 Целочисленные и беззнаковые целые числа

1 Когда значение с целым типом преобразуется в другой целочисленный тип, отличный от _Bool, если значение может быть представлено новым типом, оно не изменяется.
2 В противном случае, если новый тип без знака, значение преобразуется путем многократного добавления или вычитания более чем максимального значения, которое может быть представлено в новом типе, пока значение не будет в диапазоне нового типа. 60)
3 В противном случае новый тип подписан и значение не может быть представлено в нем; либо результат определяется реализацией, либо генерируется сигнал, определяемый реализацией.

Все это не имеет ничего общего с переменными функциями, рекламными акциями по умолчанию и т. Д.

Предполагая, что ваша система имеет подписанные символы, тогда x = 128; выполняет задание за пределами диапазона. Поведение этого определяется реализацией ; что компилятор может выбрать действие, но он должен документировать, что он делает (и, следовательно, сделать это надежно). Это действие разрешено включать в себя повышение сигнала.

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

В двоичном представлении 128 – 000....00010000000 . Усечение этого в подписанный символ дает подписанный символ двоичного представления 10000000 . В представлении дополнений двух , которое используется всеми современными системами С для отрицательных чисел, это представление значения -128 . (Для исторической любознательности: в дополнении это -127 , а в знаковой величине это -0 которое может быть ловушечным представлением и тем самым повышать сигнал).

Наконец, printf точно печатает значение этого символа -128 . Модификатор %d работает для char из-за рекламных акций по умолчанию и фактов, которые INT_MIN <= CHAR_MIN и INT_MAX >= CHAR_MAX .; это поведение гарантируется, за исключением систем, которые имеют простой символ как unsigned, и sizeof(int)==1 (которые существуют, но вы знали бы об этом, если бы были на одном).

Давайте посмотрим на двоичное представление 128 при сохранении в 8 бит:

1000 0000

И теперь давайте посмотрим на двоичное представление -128 при сохранении в 8 бит:

1000 0000

Стандарт для char с вашей текущей настройкой выглядит как signed char (обратите внимание, что это не в стандарте c, посмотрите здесь, если вы мне не верите), и поэтому, когда вы назначаете значение 128 x , повторно присваивая ему значение 1000 0000 и, таким образом, когда вы его компилируете и распечатываете, он распечатывает подписанное значение этого двоичного представления (значение -128 ).

Оказывается, моя среда одинакова в предположении, что char фактически signed char . Как и ожидалось, если я передам x как unsigned char тогда я получаю ожидаемый вывод 128 :

 #include  #include  int main() { char x; x = 128; printf("%d %d\n", x, (unsigned char)x); return 0; } 

дает мне выход -128 128

Надеюсь это поможет!