Чар подписан или не подписан по умолчанию?


158

В книге «Полная справка о С» упоминается, что char по умолчанию она не подписана.

Но я пытаюсь проверить это с помощью GCC, а также Visual Studio. Это принимает как подписано по умолчанию.

Который правильный?


5
Единственный справочник C, которому я доверяю, - это "C: Справочное руководство" Harbison & Steele ( careferencemanual.com ). Конечно, стандарт - это последнее слово, но он не очень читабелен и дает лишь малейшую информацию о предстандартном и обычном (то есть, POSIX) использовании, которые находятся за пределами стандарта. Harbison & Steele довольно читабелен, детален и, вероятно, более точен, чем большинство ссылок. Однако это также не учебник, поэтому, если вы находитесь на начальных этапах обучения, вам, вероятно, не стоит прыгать.
— Майкл Берр

15
Я думаю, что книга, которую вы читаете, называется C: The Complete Reference , написанная Гербертом Шильдтом. Из обзора этой книги ( accu.informika.ru/accu/bookreviews/public/reviews/c/c002173.htm ): я не собираюсь рекомендовать эту книгу (слишком многие из вас придают слишком большое значение моему мнению), но Я не думаю, что это заслуживает того же осуждения, которое было законно брошено на некоторые другие его работы. Как говорит Майкл, гораздо лучше справиться с Harbison & Steele .
— Алок Сингхал

Мои два цента здесь: Потому что charмогут быть без знака, как правило, использовать intдля чтения значения с использованием getchar(), которое может вернуть EOF. EOFобычно определяется как -1или другое отрицательное значение, сохранение unsignedкоторого не является тем, что вы хотите. Вот декларация: extern int getchar();Кстати, эта рекомендация также взята из книги "C: Справочное руководство".
— Максим Четруска

6
Единственная ссылка C, которой я доверяю, - это ISO / IEC 9899: 2011 :-)
— Джефф

3
@MaxChetrusca хороший совет, но плохое обоснование: даже для подписанного charслучая вам придется использовать intдля хранения возвращаемого значения.
— Антти Хаапала

Ответы:


204

Книга не права. Стандарт не определяет, является ли обычный charподписанным или неподписанным.

На самом деле, стандарт определяет три различных типа: char, signed char, и unsigned char. Если вы, #include <limits.h>а затем посмотрите CHAR_MIN, вы можете узнать, charявляется ли значение равным signedили unsigned(если CHAR_MINоно меньше 0 или равно 0), но даже тогда эти три типа различны. в отношении стандарта.

Обратите внимание, что charэто особенный способ. Если вы объявляете переменную, так как intона на 100% эквивалентна объявлению ее как signed int. Это всегда верно для всех компиляторов и архитектур.


1
@Alok: то же самое не верно для некоторых других типов данных, например, intозначает signed intвсегда, верно? Кроме charкаких других типов данных есть такая же путаница C?
— Lazer

8
@eSKay: да, charэто единственный тип, который может быть подписан или не подписан. intэквивалентно, signed intнапример.
— Алок Сингхал,

28
Есть истерическая, э-э, историческая причина этого - в начале жизни C «стандарт» переворачивался как минимум дважды, и некоторые популярные ранние компиляторы заканчивались тем или иным способом, а другие - другим.
— Hot Licks

9
@AlokSinghal: Также определяется, определено ли битовое поле типа со знаком intили без знака.
— Кит Томпсон

@KeithThompson спасибо за исправление. Я склонен забывать некоторые детали о типах битовых полей, так как я их мало использую.
— Алок Сингхал

67

Как указывает Алок , стандарт оставляет это до реализации.

Для gcc значение по умолчанию подписано, но вы можете изменить это с помощью -funsigned-char. примечание: для gcc в Android NDK по умолчанию используется без знака . Вы также можете явно запросить подписанные символы с -fsigned-char.

На MSVC значение по умолчанию подписано, но вы можете изменить его с помощью /J.


2
Интересно, что описание Шильдта не соответствует поведению MSVC, так как его книги обычно ориентированы на пользователей MSVC. Интересно, изменил ли MS по умолчанию в какой-то момент?
— Майкл Берр

1
Я думал, что это зависит не от компилятора, а от платформы. Я думал, что char был оставлен как третий тип «символьного типа данных», чтобы соответствовать тому, что системы в то время использовали как печатные символы.
— Spidey

10
НКА документы говорят , что машинно-зависимый: « Каждый вид машины имеет значение по умолчанию для того, что символ должен быть Это либо как неподписанный символ по умолчанию или как подписанный полукокс по умолчанию.. »
— Deduplicator

1
Можете ли вы предоставить источник для вашей заметки, что на Android по умолчанию является unsigned char?
— Phlipsy

1
@Spidey Стандарт C не проводит различий между компиляторами, платформами и архитектурами ЦП. Это просто смешивает их все вместе под «реализацией».
— plugwash

35

C99 N1256 черновик 6.2.5 / 15 «Типы» говорит о подписи типа char:

Реализация должна определять символ, чтобы иметь тот же диапазон, представление и поведение, что и подписанный символ или неподписанный символ.

и в сноске:

CHAR_MIN, определенный в <limits.h>, будет иметь одно из значений 0или SCHAR_MIN, и это может быть использовано для различения двух вариантов. Независимо от сделанного выбора, он charявляется отдельным типом от двух других и не совместим ни с одним из них.


7

В соответствии с книгой языка программирования C Дениса Ритчи, которая является де-факто стандартной книгой для ANSI C, простые символы, подписанные или неподписанные, зависят от машины, но печатные символы всегда положительны.


9
Это не обязательно тот случай, когда печатные символы всегда положительны. Стандарт C гарантирует, что все члены базового набора символов выполнения имеют неотрицательные значения.
— Кит Томпсон

7

В соответствии со стандартом C подпись простого char - это «определение реализации».

В общем, разработчики выбирали тот, который был бы более эффективен для реализации на их архитектуре. На системах x86 char обычно подписывается. На системах arm это вообще без знака (Apple iOS - исключение).



2
@plugwash Ваш ответ, вероятно, был отклонен, потому что Тим Пост потерял свои ключи . Если серьезно, вам не следует беспокоиться об одном понижении, если вы уверены, что ваш ответ правильный (что в данном случае так и есть). Несколько раз со мной случалось, что мои посты были отклонены без уважительной причины. Не беспокойтесь об этом, иногда люди просто делают странные вещи.
— Дональд Дак,

1
Почему подписанный char более эффективен на x86? Есть источники?
— Мартинкунев

2

Согласно «Языку программирования C ++» Бьярна Страуструпа, char«определяется реализацией». Это может быть signed charили в unsigned charзависимости от реализации. Вы можете проверить, charподписано или нет, используя std::numeric_limits<char>::is_signed.


9
Это вопрос C. C ++ - это другой язык, и ссылки на C ++ не имеют отношения к C.
— ММ

1

Теперь мы знаем, что стандарт оставляет это до реализации.

Но как проверить тип есть signedили unsigned, например char?

Я написал макрос для этого:

#define IS_UNSIGNED(t) ((t)~1 > 0)

и проверить его gcc, clangи cl. Но я не уверен, что это всегда безопасно для других случаев.


Что не так с обычным CHAR_MIN <0 (или WCHAR_MIN <0 для wchar_t)?
— Öö Tiib
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.