*** ВНИМАНИЕ: Блог переехал на другой адрес - demin.ws ***

понедельник, 9 марта 2009 г.

sizeof('a') в С и C++

В очередной раз узнал для себя новый потенциальный вопрос для "прогиба" на каком-нибудь тесте по языку С.

Программа x.c:
#include <stdio.h>
int main() {
char s[4];
s[0] = 'C'; s[1] = s[2] = '+'; s[3] = 0;
s[sizeof(' ') ^ 5] = 0;
printf("%s\n", s);
return 0;
}
Компилируем и запускаем.

Visual Studio:
cl x.c && x
или в Cygwin:
gcc -o x x.c && x
Имеем следующий результат:
C
А теперь так:
cl /TP x.c && x
или в Cygwin:
g++ -o x x.c && x
Теперь программа печает иное:
C++
Результат повеселил некоторых моих коллег.

Нашел небольшой список еще некоторых "отличий" С и С++, но, пожалуй, этот самый неявный, а значит потенциально опасный.

9 комментариев:

  1. Прикольно, однако ожидаемо. Стандарт не регламентирует, что просто char будет 1 байт. sizeof(unsigned char) будет 1. Это точно. А просто char запросто может быть равен int.

    А вот в вашем примере правильнее делать sizeof(s[0]) все-таки.

    ОтветитьУдалить
  2. Да, если изменить на s[0] все будет очевидно. Тут проблема именно в интерпретации символьной константы типа 'a'. В C это int и как результат, например 4, а в С++ это char, то есть стопудово 1.

    Конечно, мало кто в здравом уме будет писать sizeof('a') без какой-то особой коварной цели, но уж если напишет, то будет долго ловить этот глюк.

    ОтветитьУдалить
  3. 2bialix:
    ой ли - таки стандарт не регламентирует sizeof(char) ? Кёрниган и Ричи пишут как раз, о том, что sizeof(char) в Си всегда 1.

    ОтветитьУдалить
  4. sizeof(char) - это всегда 1, а не только sizeof(unsigned char), а вот sizeof('a') - это зависит от С или C++

    Стандарт не гарантирует значение sizeof(wchar_t), это да.

    ОтветитьУдалить
  5. Не вкурил зачем вы в примере пишете в неинициализированную память?

    ОтветитьУдалить
  6. Точнее не в неинициализированную память а за границу стека (см. предыдущий коммент)

    ОтветитьУдалить
  7. В каком именно месте происходит выход на границу стека?

    ОтветитьУдалить
  8. Смотрите char s[4]; в и далее s[sizeof(' ') ^ 5] = 0; XOR для С++ дает 4, т.е. запись в 5-й элемент массива, хотя на стеке было выделено 4.

    ОтветитьУдалить
  9. Факт. Эх, хотел извернуться как-нибудь оригинально, но в итоге вышло как всегда.

    Надо было не умничать, а просто написать:

    #include <stdio.h>
    int main() {
      printf(sizeof('a') == 1 ? "C++" : "C");
    }

    ОтветитьУдалить