Почему символьные литералы типа C вместо символов?

В С ++, sizeof('a') == sizeof(char) == 1. Это имеет интуитивный смысл, поскольку 'a' является буквенным символом, а sizeof(char) == 1 - определенным стандартом.

В С, однако, sizeof('a') == sizeof(int). То есть, похоже, что символьные литералы C на самом деле являются целыми числами. Кто-нибудь знает почему? Я могу найти множество упоминаний об этой причуде Си, но не могу объяснить, почему она существует.

вопрос задан 11.01.2009
Joseph Garvin
9604 репутация

12 ответов


  • 36 рейтинг

    обсуждение по той же теме

    «Более конкретно, интегральные акции. В K & R C это было практически (? ) невозможно использовать символьное значение без того, чтобы его сначала повысили до int, таким образом, делая символьной константой int в первую очередь, исключается этот шаг. Были и остаются многосимвольные константы, такие как abcd или многие поместятся в инт. "

    ответ дан Malx, с репутацией 907, 11.01.2009
  • 21 рейтинг

    Я не знаю конкретных причин, почему символьный литерал в C имеет тип int. Но в C ++ есть веская причина не идти по этому пути. Учтите это:

    void print(int);
    void print(char);
    
    print('a');
    

    Можно ожидать, что вызов для печати выбирает вторую версию с символом. Наличие литерала персонажа в виде int сделало бы это невозможным. Обратите внимание, что в C ++ литералы, имеющие более одного символа, все еще имеют тип int, хотя их значение определяется реализацией. Итак, 'ab' имеет тип int, а 'a' имеет тип char.

    ответ дан Johannes Schaub - litb, с репутацией 398434, 11.01.2009
  • 16 рейтинг

    , используя gcc на моем MacBook, я пытаюсь:

    #include 
    #define test(A) do{printf(#A":\t%i\n",sizeof(A));}while(0)
    int main(void){
      test('a');
      test("a");
      test("");
      test(char);
      test(short);
      test(int);
      test(long);
      test((char)0x0);
      test((short)0x0);
      test((int)0x0);
      test((long)0x0);
      return 0;
    };
    

    , который при запуске дает:

    'a':    4
    "a":    2
    "":     1
    char:   1
    short:  2
    int:    4
    long:   4
    (char)0x0:      1
    (short)0x0:     2
    (int)0x0:       4
    (long)0x0:      4
    

    , который предполагает, что символ - это 8 бит, как вы подозреваете, но литерал символа - это int.

    ответ дан dmckee, с репутацией 77061, 11.01.2009
  • 6 рейтинг

    Я помню, как читал K & amp; R и видел фрагмент кода, который будет читать символ за раз, пока он не достигнет EOF. Поскольку все символы являются допустимыми символами в файле / входном потоке, это означает, что EOF не может иметь никакого значения char. То, что сделал код, заключалось в том, чтобы поместить символ чтения в int, затем проверить на EOF, а затем преобразовать в символ, если это не так.

    Я понимаю, что это не совсем отвечает на ваш вопрос, но было бы разумно, чтобы остальные литералы символов были sizeof (int), если бы литерал EOF был.

    int r;
    char buffer[1024], *p; // don't use in production - buffer overflow likely
    p = buffer;
    
    while ((r = getc(file)) != EOF)
    {
      *(p++) = (char) r;
    }
    
    ответ дан Kyle Cronin, с репутацией 57340, 11.01.2009
  • 5 рейтинг

    Я не видел обоснования для этого (литералы C char являются типами int), но вот что сказал Страуструп по этому поводу (из Design and Evolution 11). 2. 1 - мелкозернистое разрешение):

    В C типом символьного литерала, например 'a', является int. Удивительно, но предоставление 'a' типа char в C ++ не вызывает проблем совместимости. За исключением патологического примера sizeof('a'), каждая конструкция, которая может быть выражена как в C, так и в C ++ дает одинаковый результат.

    Так что по большей части это не должно вызывать проблем.

    ответ дан Michael Burr, с репутацией 277528, 11.01.2009
  • 1 рейтинг

    Это правильное поведение, называемое «интегральное продвижение». Это может произойти и в других случаях (в основном, бинарные операторы, если я правильно помню).

    РЕДАКТИРОВАТЬ: Просто чтобы быть уверенным, я проверил свою копию Программирование на Expert C: Deep Secrets , и я подтвердил, что литерал char не начинается с типа int . Первоначально он имеет тип char , но когда он используется в выражении , он повышается до до int . Следующее цитируется из книги:

    Символьные литералы имеют тип int и они добираются туда, следуя правилам для продвижения от типа char. Это слишком кратко освещено в K & R 1, на странице 39 где написано:

    Каждый символ в выражении преобразован в Int. , , , Заметить, что все выражения в выражении преобразован в двойной. , , , Так как аргумент функции является выражением, преобразования типов также имеют место, когда аргументы передаются в функции: в в частности, char и short становятся int, float становится двойным

    ответ дан PolyThinker, с репутацией 4661, 11.01.2009
  • 0 рейтинг

    Я не знаю, но я собираюсь догадаться, что так проще было реализовать, и это не имело значения. Только в C ++, когда тип мог определить, какая функция будет вызвана, ее нужно исправить.

    ответ дан Roland Rabien, с репутацией 6342, 11.01.2009
  • 0 рейтинг

    Я действительно не знал этого. До появления прототипов все, что более узкое, чем int, преобразовывалось в int при использовании его в качестве аргумента функции. Это может быть частью объяснения.

    ответ дан Blaisorblade, с репутацией 5370, 11.01.2009