Я пытаюсь напечатать обугленного, как положительное значение:Как печатать символ без знака в C?
char ch = 212;
printf("%u", ch);
, но я получаю:
4294967252
Как я могу получить 212
на выходе?
Я пытаюсь напечатать обугленного, как положительное значение:Как печатать символ без знака в C?
char ch = 212;
printf("%u", ch);
, но я получаю:
4294967252
Как я могу получить 212
на выходе?
возвещать ch
в
unsigned char ch = 212 ;
И ваша Printf будет работать.
Это потому, что в этом случае в вашей системе подписан код char
*. Когда это происходит, данные становятся расширенными во время конверсий по умолчанию при передаче данных функции с переменным числом аргументов. Так как 212 больше, чем 0х80, он рассматривается как негативные, %u
интерпретирует число как большое положительное число:
212 = 0xD4
Когда по знаку, FF
s предварительно затрачиваемого на ваш номер, так что становится
0xFFFFFFD4 = 4294967252
который является номером, который печатается.
Обратите внимание, что это поведение специфично для вашей реализации. В соответствии со спецификацией C99, все char
типы назначен (подпись) int
, поскольку int
может представлять все значения из char
, знаком или без знака:
6.1.1.2: Если
int
может представлять все значения первоначальный тип, значение преобразуется вint
; в противном случае он преобразуется вunsigned int
.
В результате прохождения int
к спецификатору формата %u
, который ожидает unsigned int
.
Чтобы избежать неопределенного поведения в вашей программе, добавить явные приведения типов следующим образом:
unsigned char ch = (unsigned char)212;
printf("%u", (unsigned int)ch);
char
до реализации. См.
this question для более подробной информации.
Этот ответ путается и неточен.Предложения о расширении знака и обработке 212 представлены без контекста, не объясняя, где они применяются (более раннее предложение применяется к более поздней операции, целая продвижение символа 'char', когда оно используется в качестве аргумента, в то время как более позднее предложение применяется к более ранняя операция, инициализация 'char' с помощью' int'). –
Утверждение, что 212 считается отрицательным, потому что оно больше 0x80, является ложным. Во-первых, инициализация подписанного 'char' с 212 вызывает переполнение целых чисел в большинстве реализаций C, поэтому поведение не определено. Во многих реализациях C это приводит к усечению представления двоичного представления от 212 до восьми бит, что заставляет биты интерпретироваться как отрицательное значение, потому что бит 0x80 установлен, а не потому, что начальное значение больше 0x80 (контрпримеры включают 0x80 и 0x100). –
После инициализации 'char' он используется как аргумент' printf'. Выполняются целые рекламные акции, в результате чего отрицательный 'int' передается' printf'. Опять же, многие реализации C используют два дополнения, поэтому расширение знака выполняется, как говорится в этом ответе. Преобразование значения в 'unsigned' в этой точке даст большое положительное число. Однако этот ответ не объясняет, что фактическое поведение не определено стандартом C, потому что 'int' передается для спецификатора'% u', который ожидает 'unsigned int'. –
Диапазон знаков от 127 до -128. Если вы назначили 212, ch-магазины -44 (212-128-128) не 212. Так что, если вы попытаетесь напечатать отрицательное число как unsigned, вы получите (MAX-значение unsigned int) -abs (number), который в этом случае является 4294967252
так что, если вы хотите хранить 212, как в гл единственное, что вы можете сделать, это объявить ч, как
unsigned char ch;
теперь диапазон ч составляет от 0 до 255.
«Диапазон диапазона от 127 до -128». - Нет, диапазон определяется реализацией. –
@Jim Что вы имеете в виду? – banarun
Я имею в виду то, что я сказал ... было ясно. Символ не обязательно обязательно 8 бит, пусть вместе обязательно подписан. –
В этом коде есть две ошибки. Во-первых, в большинстве реализаций C с подписанным char
происходит переполнение в char ch = 212
, потому что 212 не подходит в 8-разрядной подписанной char
, а стандарт C не определяет поведение при переполнении целых чисел. Вместо этого она должна быть:
unsigned char ch = 212;
Во-вторых, в printf("%u",ch)
, ch
будет повышен до int
в нормальных реализациях C. Однако спецификатор %u
ожидает unsigned int
, а стандарт C не определяет поведение при передаче неправильного типа. Вместо этого она должна быть:
printf("%u", (unsigned) ch);
Я бы предложил использовать static_cast вместо старого стиля. – ShitalShah
@ShitalShah: вопрос помечен C, а не C++. C не имеет оператора static_cast. –
Ах .. не видел этого. – ShitalShah
Поскольку char
по умолчанию signed
заявил, что означает, что диапазон переменной
-127 до +127>
ваше значение переполнена. Чтобы получить желаемое значение, вам необходимо объявить модификатор unsigned
. (unsigned
) Диапазон модификатора заключается в следующем:
0 to 255
, чтобы получить диапазон любого типа данных следить за процессом 2^bit
пример char
8 битовой длины, чтобы получить свой диапазон просто 2 ^(power) 8
.
В случае, если вы не можете изменить декларацию по какой-либо причине, вы можете сделать:
char ch = 212;
printf("%d", (unsigned char) ch);
Даже с 'ch' изменен на' беззнаковое char', поведение кода не определено стандартом C. Это связано с тем, что 'unsigned char' продвигается до' int' (в обычных реализациях C), поэтому 'int' передается' printf' для спецификатора '% u'. Однако '% u' ожидает' unsigned int', поэтому типы не совпадают, а стандарт C не определяет поведение. –
Ваш комментарий неверен. В стандарте C11 указано, что спецификатор преобразования должен быть того же типа, что и функция 'argument', а не продвинутый тип. Этот пункт также специально рассматривается в описании модификатора длины hh: «аргумент будет продвигаться в соответствии с целыми рекламными акциями, но его значение должно быть преобразовано в подписанный символ или без знака перед печатью» –
Работает только после явного приведения в 'unsigned int' при передаче в' prtinf() '. Добавление -std = c11 в команду gcc-4.8.4 для принудительного применения стандарта не повлияло. – ypx