Печать символа с помощью printf - PullRequest
18 голосов
/ 19 января 2011

Оба эти кода одинаковы

char ch = 'a';
printf("%d", ch);

Будет ли печататься значение мусора?

Я запутался в этом

printf("%d", '\0'); 

Будет ли это печатать 0 или значение мусора? Потому что, когда я делаю это

printf("%d", sizeof('\n')); 

Он печатает 4. Почему sizeof('\n') 4 байта? То же самое в C ++ печатает 1 байт. Почему это?

Так вот главный вопрос

на языке c printf("%d", '\0') должен печатать 0

а в C ++ printf("%d", '\0') предполагается печатать мусор?

Ответы [ 6 ]

35 голосов
/ 19 января 2011

%d печатает целое число: оно напечатает ascii представление вашего персонажа.Вам нужно %c:

printf("%c", ch);

printf("%d", '\0'); печатает представление ascii '\0', которое равно 0 (экранируя 0, вы указываете компилятору использовать значение ascii 0.

printf("%d", sizeof('\n')); печатает 4, потому что символьный литерал является int в C, а не char.

8 голосов
/ 19 января 2011

Предполагается, что для вывода значения символа ASCII используется символ, поскольку %d - escape-последовательность для целого числа Таким образом, значение, указанное в качестве аргумента printf, принимается как целое число при печати. ​​

char ch = 'a';
printf("%d", ch);

То же самое относится к printf("%d", '\0');, где символ NULL интерпретируется как целое число 0.

Наконец, sizeof('\n') равно 4, потому что в C это обозначение для символов обозначает соответствующее целое число ASCII. Так что \ n равно 10 как целое число.

Все зависит от толкования байтов.

6 голосов
/ 19 января 2011

В C символьные константные выражения, такие как '\n' или 'a', имеют тип int (таким образом sizeof '\n' == sizeof (int)), тогда как в C ++ они имеют тип char.

Оператор printf("%d", '\0'); должен просто вывести 0; тип выражения '\0' равен int, а его значение равно 0.

Оператор printf("%d", ch); должен печатать целочисленную кодировку для значения в ch (для ASCII, 'a' == 97).

5 голосов
/ 19 января 2011

В C char повышается до int в выражениях.Это в значительной степени объясняет каждый вопрос, если вы об этом думаете.

Источник: Язык программирования C от Брайана В. Кернигана и Денниса М. Ритчи

Если вы хотите изучать C, то вы должны прочитать.

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

3 голосов
/ 01 марта 2014
#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;
}
0 голосов
/ 20 января 2011

Да, он печатает GARBAGE, если вам не повезет.

ОЧЕНЬ ВАЖНО.

Тип аргумента printf / sprintf / fprintf ДОЛЖЕН соответствовать ассоциированному типу формата char.

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

Многие новые компиляторы знают о printf и выдают предупреждения, если типы не совпадают. Если вы получили эти предупреждения, исправьте их.

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

printf("%d\n", (int) ch)

В этом примере printf сообщается, что в стеке есть «int». Приведение гарантирует, что независимо от того, что возвращает sizeof (обычно это какое-то длинное целое число), printf получит int.

printf("%d", (int) sizeof('\n'))
...