В C как определяется, идентичны ли два типа?

0

Из

http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/index.jsp?topic=/com.ibm.vacpp7a.doc/language/ref/clrc03compatible_types.htm

Наличие спецификаторов типов в различных комбинациях для арифметических типов может указывать или не указывать разные типы. Например, тип, подписанный int, такой же, как и int, за исключением случаев, когда они используются как типы битовых полей; но char, signed char и unsigned char - разные типы.

В чем причина этой разницы между int и char в отношении идентичности типа?

Я думаю, что те же правила применяются и в C++. Поэтому добавление тега C++ также к этому вопросу

  • 2
    Вы хотите знать, как определить, идентичны ли типы или почему подпись char отличается? Это разные вопросы.
  • 4
    Исторически, до появления языкового стандарта, в некоторых системах char был подписан, а в других - нет. Это поведение стандартизировано для обратной совместимости: оно определяется реализацией, независимо от того, является ли char подписанным или неподписанным. С другой стороны, int всегда рассматривался как подписанный везде, поэтому такие махинации не нужны.
Показать ещё 2 комментария
Теги:

2 ответа

3
Лучший ответ

Первоначально C не имел unsigned типов, поэтому char был подписан по умолчанию. Поскольку PDP-11 использовал 8-битные байты и набор символов ASCII, объекты char не ожидали принимать отрицательные значения:

Символы (объявленные и именуемые далее char) выбираются из набора ASCII; они занимают самые правые семь бит 8-битного байта. Также возможно интерпретировать char как подписанный, 2s дополнять 8-битные номера.

unsigned типы были добавлены примерно в 1977 году частично, чтобы препятствовать использованию указателей для беззнаковой арифметики:

[...] сходство арифметических свойств указателей символов и целых чисел без знака затрудняло искушение их идентифицировать. Для создания беззнаковой арифметики были добавлены типы без знака, не путая их с манипуляцией указателем.

Проблема с созданием char заключается в том, что для выполнения арифметики по значениям char необходимо подписать-расширять их. Это было эффективно на PDP-11, в котором была инструкция SXT, но не на ARM (по крайней мере, до версии 4 архитектуры ARM, выпущенной в 1996 году):

[...] вы не найдете ни одного "символа нагрузки из памяти и расширения знака" в наборе команд ARM. Поэтому, по соображениям производительности, каждый компилятор, о котором я знаю, делает тип символа по умолчанию, подписанный на x86, но без знака в ARM. [...]

Таким образом, когда C был стандартизирован, у комитета был выбор либо сделать char - и, таким образом, заставить реализации ARM измениться, чтобы стать неэффективными, или отразить существующую практику и сделать подписку на определение реализации char.

  • 0
    +1 Спасибо за раннюю ссылку на Справочное руководство C. Интересно отметить end-of-file ( ´\0´ returned from "getchar" )" , поэтому EOF было 0, BITD.
  • 0
    Благодарю. У ARM не было расширенной загрузки знака только для символов, но была такая инструкция для коротких (16-битных слов)?
Показать ещё 1 комментарий
3

Из C++ 11: (фрагменты из различных абзацев в § 3.9)

Обычный символ, подписанный символ и unsigned char - это три разных типа, которые в совокупности называются узкими типами символов.

Существует пять стандартных стандартных целочисленных типов: "signed char", "short int", "int", "long int" и "long long int".
Для каждого стандартного знакового целочисленного типа существует соответствующий (но другой) стандартный беззнаковый

целочисленный тип: "unsigned char", "unsigned short int", "unsigned int", "unsigned long int" и "unsigned long long int", каждый из которых занимает одинаковое количество хранения и имеет те же требования к выравниванию (3.11 ) в качестве соответствующего знакового целочисленного типа47;

Тип wchar_t - это отдельный тип... Типы char16_t и char32_t обозначают разные типы...

Значения типа bool являются либо истинными, либо ложными.49 [Примечание. Нет никаких подписанных, неподписанных, коротких или длинных типов или значений bool. -End note]

В п. 7.1.6.2 перечислены таблицы, ключевые слова которых приводят к тому, какие типы:

type-name          the type named
simple-template-id the type as defined in 14.2
char               "char"
unsigned char      "unsigned char"
signed char        "signed char"
char16_t           "char16_t"
char32_t           "char32_t"
bool               "bool"
unsigned           "unsigned int"
unsigned int       "unsigned int"
signed             "int"
signed int         "int"
int                "int"
unsigned short int "unsigned short int"
unsigned short     "unsigned short int"
unsigned long int  "unsigned long int"
unsigned long      "unsigned long int"
unsigned long long int "unsigned long long int"
unsigned long long "unsigned long long int"
signed long int    "long int"
signed long        "long int"
signed long long int "long long int"
signed long long   "long long int"
long long int      "long long int"
long long          "long long int"
long int           "long int"
long               "long int"
signed short int   "short int"
signed short       "short int"
short int          "short int"
short              "short int"
wchar_t            "wchar_t"
float              "float"
double             "double"
long double        "long double"
void               "void"
auto               placeholder for a type to be deduced
decltype(expression) the type as defined below

Что касается причины, почему char является wierd, мне сказали, что первоначально, был какой-то компилятор, который сделал char unsigned (до того, как были созданы unsigned типы?). Стандарт C++ хотел исправить это, но не хотел нарушать существующий код, поэтому они сделали подписанность реализации char определенной и добавили signed char как отдельный тип.

  • 0
    Возможно, вы захотите указать, как квалификаторы: const , volatile , restrict влияют или не влияют на типы.
  • 1
    @chux: я не могу придумать краткий способ точно описать const и volatile потому что это часто бывает да, а иногда нет. Я не знаком с restrict вообще.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню