sizeof для символа кириллицы

432
23 декабря 2016, 14:25

Я провел несколько экспериментов, но объяснить почему это так работает я не смог

Пример 1:

#include <stdio.h>
int main() {
    /// латиница
    printf("\n%d",sizeof('a')); /// 1
    /// кириллица
    printf("\n%d",sizeof('ф')); /// 4
    return 0;
}

Пример 2:

#include <stdio.h>
int main() {
    char a = 'a'; /// латиница
    char b = 'ф'; /// кириллица
    printf("\n%d",sizeof(a)); /// 1
    printf("\n%d",sizeof(b)); /// 1
    return 0;
}

Вообще ничего не понимаю объясните! P.S Компилятор g++

Answer 1

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

Следует заметить, что оба варианта Вашего кода при попытке компиляции компилятором clang приводят к ошибке:

error: character too large for enclosing character literal type  
char b = 'ф'; /// кириллица

А используемый Вами gcc даёт пару предупреждений для строки с буквой ф:

warning: multi-character character constant [-Wmultichar]  
warning: overflow in implicit constant conversion [-Woverflow]

Первое говорит об использовании мультисимвольного литерала (что поддерживается не всеми компиляторами). Второе - о том, что этот литерал не помещается в char. Т.е. тип 'ф' компилятором был интерпретирован как нечто большее, чем char, и, как уже упоминалось в цитате из ответа @Harry, этот тип есть int:

... has type int, and has an implementation-defined value.

Исходя из вышесказанного, можно сделать вывод:

  • 4 (пример 1) получается, т.к. мультисимвольный литерал не усекается и его размер равен размеру int, т.е. sizeof(int) == 4.
  • 1 (пример 2) получается, т.к. мультисимвольный литерал был усечён до типа char при инициализации переменной b, а sizeof(char) == 1 по определению.

Отвечу здесь и на Ваш комментарий к другому сообщению:

я представлял себе многобайтовый литерал как один символ из сложной кодировки допустим 'ф' (UTF-8) а это 2 байта выходит мы можем по вашим словам записать не более 2х 'ф'...несостыковочка с 4мя символами

Записать более 2х 'ф' у Вас действительно не получится.

#include <stdio.h>
int main() {
    printf("\n%d",sizeof('ффф')); 
}
warning: character constant too long for its type

Т.е. фактически происходит усечение значения до sizeof(int).

Но если будет использован строковый литерал, то для хранения ф вполне может хватить двух байт:

#include <stdio.h>
int main() {
    const char c[] = "ф";
    printf("%ld\n", sizeof(c)); 
}

3

Выводит число 3, т.к. 1 байт отводится под терминирующий ноль.

Answer 2

sizeof - формально не функция, а оператор, который еще во время компиляции дает размер типа - т.е. сколько памяти требуется для хранения переменной данного типа.

Судя по тому, что для латинского литерала 'a' вы получили значение 1, вы компилируете не как C, а как C++! В чистом C литерал символа приводится к типу int, и вы бы получили 4.

Приходится также полагать, что исходник у вас сохранен как utf-8, например, так что кириллица раскрывается в нечто большее, чем char, и это нечто приводится к int и дает 4.

Последние же строки получают не литерал, а переменную типа char, а для нее в C++ однозначно - sizeof(char) == 1.

Вот и все...

P.S. Поскольку некоторые настаивают... :) Из стандарта о символьных литералах:

An ordinary character literal that contains a single c-char representable in the execution character set has type char, with value equal to the numerical value of the encoding of the c-char in the execution character set. An ordinary character literal that contains more than one c-char is a multicharacter literal. A multicharacter literal, or an ordinary character literal containing a single c-char not representable in the execution character set, is conditionally-supported, has type int, and has an implementation-defined value.

Answer 3

Тип однобайтового символьного литерала 'q' - это char, sizeof(char) равен 1.

Тип многобайтового символьного литерала 'qq' - это int, sizeof(int) это например 4.

Если исходники сохраняются в кодировке utf-8, то литерал 'ф' это два байта, он эквивалентен '\xd1\x84'. Соответственно его тип - int.

READ ALSO
Ошибка компиляции LNK 2005

Ошибка компиляции LNK 2005

Список ошибок:

282
Qt | Работа с layout&#39;ами

Qt | Работа с layout'ами

Есть QTabWidgetВ его вкладку нужно добавить виджет, например QLabel

402
Вопрос о итераторах [требует правки]

Вопрос о итераторах [требует правки]

В каких случаях программа при отладке выдаёт ошибку: vector iterator not dereferencable и как ее, примерно, можно исправить?

314
QScrollArea и Layout

QScrollArea и Layout

Есть QScrollAreaВ нее нужно засунуть n-ое количество виджетов так, чтобы все скролилось при нужде

380