Печать char с помощью printf
Оба эти кода одинаковы
char ch = 'a';
printf("%d", ch);
Будет ли он печатать значение мусора?
Я смущен об этом
printf("%d", '\0');
Будет ли это печатать 0 или значение мусора?
Потому что, когда я делаю это
printf("%d", sizeof('\n'));
Он печатает 4. Почему sizeof('\n')
4 байта?
То же самое в С++ печатает 1 байт. Почему это?
Итак, главный вопрос
в языке c printf("%d", '\0')
предполагается напечатать 0
и в С++ printf("%d", '\0')
должен печатать мусор?
Ответы
Ответ 1
%d
печатает целое число: оно будет печатать ascii-представление вашего символа. Вам нужно %c
:
printf("%c", ch);
printf("%d", '\0');
печатает ascii-представление '\0'
, которое равно 0 (путем экранирования 0 вы указываете компилятору использовать значение ascii 0.
printf("%d", sizeof('\n'));
выводит 4, потому что символьный литерал является int
в C, а не a char
.
Ответ 2
Предполагается напечатать значение ASCII символа, так как %d
- это escape-последовательность для целого числа. Поэтому значение, указанное как аргумент printf
, принимается как целое при печати.
char ch = 'a';
printf("%d", ch);
То же самое выполняется для printf("%d", '\0');
, где символ NULL интерпретируется как целое число 0.
Наконец, sizeof('\n')
равно 4, потому что в C это обозначение для символов означает соответствующее целое ASCII. Таким образом, '\n' совпадает с 10 как целое число.
Все зависит от интерпретации, которую вы передаете байтам.
Ответ 3
В C char
в выражениях выражается до int
. Это в значительной степени объясняет каждый вопрос, если вы думаете об этом.
Источник: язык программирования C Брайана У.Кернигана и Денниса М. Ричи
A необходимо прочитать, если вы хотите узнать C.
Также см. эту страницу, где люди, намного более опытные тогда, я могу объяснить это намного лучше, чем когда-либо.
Ответ 4
В C выражения символов, такие как '\n'
или 'a'
, имеют тип int
(таким образом, sizeof '\n' == sizeof (int)
), тогда как в С++ они имеют тип char
.
Утверждение printf("%d", '\0');
должно просто напечатать 0; тип выражения '\0'
равен int
, а его значение равно 0.
Оператор printf("%d", ch);
должен печатать целочисленную кодировку для значения в ch
(для ASCII, 'a'
== 97).
Ответ 5
#include <stdio.h>
#include <stdlib.h>
int func(char a, char b, char c) /* demonstration that char on stack is promoted to int !!!
note: this promotion is NOT integer promotion, but promotion during handling of the stack. don't confuse the two */
{
const char *p = &a;
printf("a=%d\n"
"b=%d\n"
"c=%d\n", *p, p[-(int)sizeof(int)], p[-(int)sizeof(int) * 2]); // don't do this. might probably work on x86 with gcc (but again: don't do this)
}
int main(void)
{
func(1, 2, 3);
//printf with %d treats its argument as int (argument must be int or smaller -> works because of conversion to int when on stack -- see demo above)
printf("%d, %d, %d\n", (long long) 1, 2, 3); // don't do this! Argument must be int or smaller type (like char... which is converted to int when on the stack -- see above)
// backslash followed by number is a oct VALUE
printf("%d\n", '\377'); /* prints -1 -> IF char is signed char: char literal has all bits set and is thus value -1.
-> char literal is then integer promoted to int. (this promotion has nothing to do with the stack. don't confuse the two!!!) */
/* prints 255 -> IF char is unsigned char: char literal has all bits set and is thus value 255.
-> char literal is then integer promoted to int */
// backslash followed by x is a hex VALUE
printf("%d\n", '\xff'); /* prints -1 -> IF char is signed char: char literal has all bits set and is thus value -1.
-> char literal is then integer promoted to int */
/* prints 255 -> IF char is unsigned char: char literal has all bits set and is thus value 255.
-> char literal is then integer promoted to int */
printf("%d\n", 255); // prints 255
printf("%d\n", (char)255); // prints -1 -> 255 is cast to char where it is -1
printf("%d\n", '\n'); // prints 10 -> Ascii newline has VALUE 10. The char 10 is integer promoted to int 10
printf("%d\n", sizeof('\n')); // prints 4 -> Ascii newline is char, but integer promoted to int. And sizeof(int) is 4 (on many architectures)
printf("%d\n", sizeof((char)'\n')); // prints 1 -> Switch off integer promotion via cast!
return 0;
}
Ответ 6
Да, он печатает GARBAGE, если вам не повезло.
ОЧЕНЬ ВАЖНО.
Тип аргумента printf/sprintf/fprintf ДОЛЖЕН соответствовать соответствующему типу формата char.
Если типы не совпадают и компилируются, результаты очень undefined.
Многие новые компиляторы знают о printf и выдают предупреждения, если типы не совпадают. Если вы получите эти предупреждения, исправьте их.
Если вы хотите преобразовать типы для аргументов для переменных функций, вы должны предоставить листинг (т.е. явное преобразование), потому что компилятор не может понять, что нужно выполнить преобразование (как это может быть с прототипом функции с типизированные аргументы).
printf("%d\n", (int) ch)
В этом примере printf TOLD указывает, что в стеке есть "int". Листинг гарантирует, что независимо от того, что возвращает размер sizeof (как правило, длинное целое число), printf получит int.
printf("%d", (int) sizeof('\n'))