В C, почему sizeof (char) 1, когда «a» - это int?

Я пытался

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

и получил 1, 4 на выходе. Если размер символа равен единице, почему 'c' дает мне 4? Я думаю, это потому, что это целое число. Итак, когда я делаю char ch = 'c';, происходит ли под капотом неявное преобразование из этого 4-байтового значения в 1-байтовое значение, когда оно назначается переменной char?


person legends2k    schedule 12.02.2010    source источник
comment
Я полагаю, что это связано с автоматическим целочисленным продвижением, кто-то, у кого больше фактов, чем веры, опубликует фактический ответ.   -  person Binary Worrier    schedule 12.02.2010
comment
@Roger: Он спрашивает о разнице между C и C++ sizeof('a'), а я спросил, происходит ли преобразование? См. тело вопроса. Я уже сделал вывод, что «а» — это целое число в C.   -  person legends2k    schedule 12.02.2010
comment
Я должен поблагодарить Дэвида Родригеса - dribeas за то, что он указал, что ссылка в моем ответе неверна. Я удаляю свой ответ. legends2k, по моему скромному мнению, правильный ответ должен быть у Питера или Нила.   -  person Binary Worrier    schedule 12.02.2010
comment
Я изменил принятый ответ сейчас. Спасибо за исправление Давида Родригеса - dribeas.   -  person legends2k    schedule 12.02.2010
comment
Вы получили свой ответ, но комментарий: вы не можете печатать объекты size_t с помощью "%d". Поскольку sizeof дает size_t объект size_t, вы должны напечатать его с помощью "%zu" (C99) или преобразовать его в unsigned long и напечатать с помощью "%lu" (C89).   -  person Alok Singhal    schedule 13.02.2010
comment
stackoverflow .com/questions/433895/   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 28.06.2015


Ответы (5)


В C 'a' является целочисленной константой (!?!), поэтому 4 подходит для вашей архитектуры. Он неявно преобразуется в char для назначения. sizeof(char) всегда равен 1 по определению. Стандарт не говорит, что такое единица измерения 1, но часто это байты.

person Richard Pennington    schedule 12.02.2010
comment
+1 за но это часто байты, я до сих пор посмеиваюсь :) - person Binary Worrier; 12.02.2010
comment
раньше было целым числом было 2 байта .. стандарт это тоже не определяет. - person lexu; 12.02.2010
comment
Могу ли я узнать обоснование стандарта, утверждающего, что sizeof(char) всегда должно быть 1? Это из-за того, что таблица ASCII имеет 256 символов? Что, если в реализации мне нужно больше, скажем, юникод? - person legends2k; 12.02.2010
comment
sizeof(1) всегда равен 1, потому что это то, что есть. 1 может быть один байт (например, из 8 бит) или 3 байта или .. - person Richard Pennington; 12.02.2010
comment
Стандарт определяет оператор sizeof как возвращающий размер в байтах, поэтому это происходит не часто, а всегда. Во втором абзаце «Оператор sizeof»: «Оператор sizeof возвращает размер (в байтах) своего операнда». - person David Rodríguez - dribeas; 12.02.2010
comment
sizeof(char) равен одному байту, потому что это определение байта в стандарте C. Этот байт может состоять из 8 бит или более (не может быть меньше в C) и может быть или не быть наименьшей единицей, адресуемой компьютером (определение байта, распространенное в компьютерной архитектуре). Третье распространенное определение байта — это единица, используемая для кодирования символов, например, 8 бит для UTF-8 или ISO-8859-X, 16 бит для UTF-16. Довольно часто все определения сходятся и ставят размер байта в 8 бит. Так часто, что четвертое определение байта составляет 8 бит. Когда они не согласны, вам лучше четко указать, какое определение вы используете. - person AProgrammer; 12.02.2010
comment
Я всегда содрогаюсь, когда читаю неявно приведенные в SO сообщения. Нет неявного приведения: приведение всегда является явным преобразованием. Стандарт C говорит в 6.3: Некоторые операторы автоматически преобразуют значения операнда из одного типа в другой. В этом подпункте указывается результат, требуемый от такого неявного преобразования, а также результат операции приведения (явное преобразование). Вы хотите сказать, неявное преобразование. - person Johannes Schaub - litb; 12.02.2010
comment
@lexu: int должно быть не менее 16 бит, что бы это ни означало в байтах. Поскольку sizeof() измеряется 8-битными байтами на большинстве современных компьютеров, это обычно означает не менее 2 байтов. Предполагается, что int имеет натуральный размер, что означает 2 байта на старых 16-битных машинах и 4 байта на более современных. - person David Thornley; 12.02.2010
comment
@litb: Спасибо, что поправили меня; Я исправил это в вопросе с «приведения» на «преобразование». - person legends2k; 12.02.2010
comment
sizeof() измеряет (я полагаю, целое число), кратное CHAR_BITS. Ни больше ни меньше. sizeof(char) == 1 по определению. Количество битов в другом типе можно найти, умножив sizeof(type) на CHAR_BITS. Конечно, на большинстве (если не на всех) платформах значение CHAR_BITS равно 8. - person Vatine; 12.02.2010
comment
Это всегда байты. Это могут быть не октеты. - person Lightness Races in Orbit; 17.07.2015

Стандарт C говорит, что символьный литерал типа 'a' имеет тип int, а не char. Поэтому он имеет (на вашей платформе) sizeof == 4. См. этот вопрос для более полного обсуждения.

person Community    schedule 12.02.2010
comment
Я спросил о продвижении/приведении, которое происходит между двумя типами данных, в то время как обсуждение/ответ не отвечает на это. - person legends2k; 12.02.2010
comment
@ legends2K Вы спросили, если размер символа равен единице, почему «c» дает мне 4? Поскольку этот ответ и вопрос, который я связал, объясняют, что «a» имеет sizeof == 4, очевидно, что кастинг или продвижение по службе не происходит. - person ; 12.02.2010
comment
Что ж. под ним находится подробная форма вопроса, в которой говорится, происходит ли под капотом неявное приведение типов от этого 4-байтового значения к 1-байтовому значению, когда оно присваивается переменной char. Я считаю, что это тоже часть этого. - person legends2k; 12.02.2010
comment
Продвижения нет. В C 'a' имеет тип int. В большинстве реализаций C «a» точно такое же, как 97. В C++ «a» имеет тип char. - person gnasher729; 11.04.2014

Это нормальное поведение оператора sizeof (см. Википедию):

  • Для типа данных sizeof возвращает размер типа данных. За char вы получаете 1.
  • Для выражения sizeof возвращает размер типа переменной или выражения. Поскольку символьный литерал вводится как int, вы получаете 4.
person Laurent Etiemble    schedule 12.02.2010

Это описано в ISO C11 6.4.4.4 Character constants, хотя он практически не изменился по сравнению с более ранними стандартами. В пункте /10 говорится:

Целочисленная символьная константа имеет тип int. Значение целочисленной символьной константы, содержащей один символ, который отображается на однобайтовый символ выполнения, является числовым значением представления сопоставленного символа, интерпретируемого как целое число.

person paxdiablo    schedule 11.04.2014
comment
+1 спасибо за цитирование стандарта; Интересно, почему целочисленная символьная константа была выбрана вместо символьной константы. - person legends2k; 11.04.2014

Согласно стандартам ANSI C, char повышается до int в контексте, где используются целые числа, вы использовали спецификатор целочисленного формата в printf, следовательно, разные значения. Символ обычно составляет 1 байт, но это реализация, определяемая на основе среды выполнения и компилятора.

person t0mm13b    schedule 12.02.2010
comment
Целочисленный формат относится к sizeof('a'), а не к 'a', поэтому я не понимаю, как работает этот аргумент. - person SmacL; 12.02.2010
comment
Стандарт C говорит, что литерал char имеет тип int - он имеет sizeof int и не участвует в продвижении. - person ; 12.02.2010
comment
Ваш ответ, кажется, предполагает, что компилятор C проверяет строку формата, используемую библиотечной функцией при компиляции программы, вы уверены, что это так? - person Peter van der Heijden; 12.02.2010
comment
Что, если бы это было scanf(%s\n,format) ; printf(формат, sizeof(char), sizeof('a')); и вы бы набрали %d, %d\n при появлении запроса? В этом случае компилятор не имеет возможности узнать типы переменных априори и должен слепо использовать оператор многоточия, как это и предполагалось? - person SF.; 12.02.2010
comment
@Peter van der Heijden: вы правы, строка формата и ее спецификаторы не имеют ничего общего с типами переменных, передаваемых после них. gcc будет выдавать предупреждения, если они не совпадают, но он отлично компилируется с несовпадающими типами, при условии, что вы знаете больше, чем компилятор. Тем не менее, «a» находится в sizeof, а не в целочисленном контексте. Вызовы sizeof возвращают size_t, который, как я полагаю, обычно определяется как целое число без знака. - person Michael Speer; 12.02.2010