Я провел несколько экспериментов, но объяснить почему это так работает я не смог
Пример 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++
Символьные (и строковые) литералы в коде программы так или иначе переводятся компилятором в последовательность байт. Правило этого преобразования зависит от кодировки исходника (как уже упоминали другие участники), но может зависеть и ещё от ряда факторов (см. ответ на другой вопрос).
Следует заметить, что оба варианта Вашего кода при попытке компиляции компилятором 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 байт отводится под терминирующий ноль.
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.
Тип однобайтового символьного литерала 'q'
- это char
, sizeof(char)
равен 1.
Тип многобайтового символьного литерала 'qq'
- это int
, sizeof(int)
это например 4.
Если исходники сохраняются в кодировке utf-8, то литерал 'ф'
это два байта, он эквивалентен '\xd1\x84'
. Соответственно его тип - int
.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
В каких случаях программа при отладке выдаёт ошибку: vector iterator not dereferencable и как ее, примерно, можно исправить?
Есть QScrollAreaВ нее нужно засунуть n-ое количество виджетов так, чтобы все скролилось при нужде