Имеет ли доступ к int с char * потенциально поведение undefined?
Ожидается, что код, приведенный ниже для проверки подлинности, будет иметь определенное поведение реализации:
int is_little_endian(void) {
int x = 1;
char *p = (char*)&x;
return *p == 1;
}
Но возможно ли, что это может иметь поведение undefined на специально изобретенных архитектурах? Например, первый байт представления int
со значением 1
(или другим хорошо выбранным значением) будет значением ловушки для типа char
?
Как отмечено в комментариях, тип unsigned char
не будет иметь этой проблемы, поскольку он не может иметь значения ловушки, но этот вопрос относится конкретно к типу char
.
Ответы
Ответ 1
Я не думаю, что Стандарт запретил бы реализацию, в которой signed char
использовал формат знака-знака или один-дополнительный, и попал в ловушку при попытках загрузить бит-шаблон, который будет представлять "отрицательный ноль". Также не требует, чтобы такие реализации должны были сделать char
без знака. Можно было бы изобрести архитектуру, в которой ваш код может иметь произвольное поведение. Еще несколько важных замечаний:
-
Нет никакой гарантии, что биты внутри char
отображаются в той же последовательности, что и в int
. Код не будет запускаться в UB-land, если биты не будут отображаться по порядку, но результат будет не очень значимым.
-
Насколько я могу судить, каждая неконкурентоспособная соответствующая реализация C99 использовала формат "два дополнения"; Я считаю сомнительным, что любой когда-либо будет делать иначе.
-
Было бы глупо для реализации сделать char
типом с меньшим количеством представляемых значений, чем битовые шаблоны.
-
Можно было бы придумать соответствующую реализацию, которая бы почти что-либо почти с любым исходным текстом при условии, что существует некоторый исходный текст, который будет обрабатываться в соответствии со стандартом.
Можно было бы создать подходящую реализацию знаковой величины, в которой целочисленное значение 1 будет иметь битовый шаблон, который будет кодировать подписанное значение char "отрицательный ноль" и которое будет ловушке при попытке загрузить его. Можно было бы даже придумать реализацию соответствующих дополнений, которые сделали это (у них есть много бит заполнения в типе "int", все из которых устанавливаются при сохранении значения "1" ). Учитывая, что можно было бы разработать соответствующую реализацию, которая использует правило единой программы, чтобы оправдывать выполнение чего-либо, что ему понравилось, с помощью вышеупомянутого исходного текста, независимо от того, какой целочисленный формат он использует, однако я не думаю, что вероятность странного типа char
должна действительно быть беспокойством.
Заметьте, кстати, что Стандарт не прилагает никаких усилий, чтобы запретить глупые реализации; он может быть улучшен путем добавления языка, в соответствии с которым char
должен быть либо двухкомпонентным, либо без символьных представлений, либо неподписанным типом, либо обязательным для него значением signed char
, либо явно указывая, что это не требуется. Он также может быть улучшен, если он распознает категорию реализаций, которые не могут поддерживать такие типы, как unsigned long long
[который был бы основным камнем преткновения для 36-битных систем дополнения и может быть причиной того, что не соответствует C99 для таких платформ существуют реализации].
Ответ 2
Per C 2011 [N1570] 6.2.5 15, char
ведет себя как signed char
или unsigned char
. Предположим, что оно signed char
. 6.2.6.2 2 обсуждать знаковые целочисленные типы, включая signed char
. В конце этого параграфа говорится:
Какое из этих [знака, величины, двойного дополнения или одного дополнения] применяется, определяется реализацией, равно как и значение со знаковым битом 1 и всеми битами значения 0 (для первых двух) или со знакомным битом и все биты значений 1 (для одного дополнения) представляют собой ловушечное представление или нормальное значение.
Таким образом, этот абзац позволяет signed char
иметь ловушку. Я не знаю ни одной части стандарта C, которая противоречит этому. Таким образом, доступ к байтам int
через a char *
может считывать представление ловушки и, следовательно, может иметь поведение undefined.
Конкретное значение 1 в int
не приведет к представлению ловушки в char
для любой нормальной реализации C, поскольку 1 будет находиться в самом "правом" (младшем значении) бите некоторого байта int
, и никакая нормальная реализация C не помещает бит знака char
в бит в этой позиции. Однако стандарт C, по-видимому, не запрещает такую компоновку, поэтому теоретически значение int
со значением 1 может быть закодировано битами 00000001 в одном из его байтов, и эти биты могут быть ловушечным представлением для char
.
Ответ 3
Я нашел цитату из Стандарта, которая доказывает, что никакое представление объекта не является значением ловушки для unsigned char
:
6.2.6.2 Целочисленные типы
1 Для целых чисел без знака, отличных от без знака char,, бит объекта представление делится на две группы: биты значений и биты заполнения (необходимо не быть последним). Если бит N значений бит, каждый бит должен представлять собой мощность 2 между 1 и 2N-1, чтобы объекты такого типа были способны представляющие значения от 0 до 2N - 1 с использованием чистого двоичного представления; это должно быть известный как представление значения. Значения любых битов дополнений не определены .53)
Предыдущее говорит, что unsigned char
не может иметь никаких добавочных битов.
В следующей сноске говорится, что биты заполнения - это то, что можно использовать для ловушечных представлений.
53). Некоторые комбинации битов дополнений могут генерировать ловушечные представления, например, если одно дополнение бит - бит четности. Несмотря на это, никакая арифметическая операция над допустимыми значениями не может создать ловушку представление, отличное от частичного исключительного условия, такого как переполнение, и это не может произойти с неподписанными типами. Все остальные комбинации битов дополнений представляют собой альтернативные представления объектов значение, указанное битами значения.
Итак, я думаю, что ответ заключается в том, что char
не гарантированно не имеет значений ловушек, но unsigned char
есть.