(size_t) ((символ *) 0) когда-нибудь не оценивают к 0?

Согласно ответам в, "Почему вычитают нулевого указателя в offsetof ()?" (и мое чтение K&R), стандарт C не требует этого (size_t)((char *)0) == 0. Однако, я никогда не видел ситуации, где кастинг нулевого указателя к целому типу оценивает к чему-либо еще.

Если существует компилятор или сценарий где (size_t)((char *)0) != 0, что это?

5
задан Community 23 May 2017 в 11:51
поделиться

4 ответа

Ну, как вы знаете, физическое представление null указатель данного типа не обязательно является битовой комбинацией с нулевым значением. Когда вы принудительно преобразуете значение указателя (любого указателя) в целочисленный тип, результат определяется реализацией, но обычно (и это намерение) числовое значение указателя - числовой адрес - остается неизменным, если это возможно. Это означает, что если на данной платформе нулевой указатель типа char * представлен шаблоном 0xBAADF00D (например), приведенное выше выражение будет оцениваться как 0xBAADF00D , а не до нуля. Конечно, для этого вам понадобится платформа с ненулевыми нулевыми указателями. Я лично никогда не работал с такими платформами, хотя слышал о ряде реальных платформ, подобных этой (например, в сфере встроенных платформ это не является чем-то необычным).

Кроме того, в качестве дополнительного примечания, значения нулевого указателя разных типов могут иметь различное физическое представление, что означает, что теоретически вы можете получить разные значения из (size_t) ((int *) 0) , (size_t) ((char *) 0) и (size_t) ((double *) 0) . Но это была бы довольно экзотическая ситуация, хотя вполне возможная с точки зрения абстрактного языка C.

P.S. Прочтите здесь (C FAQ), чтобы узнать о некоторых примерах реальных платформ с ненулевыми нулевыми указателями.

4
ответ дан 14 December 2019 в 13:32
поделиться

Это не относится к char * или даже к C, но класс интеллектуального указателя, который индексирует массив, может представлять NULL как -1 , потому что 0 является допустимым индексом массива.

Учитывая идиому memset (my_new_struct, 0, sizeof my_new_struct); , даже система, ориентированная на отладку, вряд ли нарушит эту идентичность.

0
ответ дан 14 December 2019 в 13:32
поделиться

Единственное, что стандарт C требует от представления времени выполнения нулевого указателя, это (6.3.2.3/3 «Указатели»):

... результирующий указатель, называемый нулевым указателем, гарантированно не равен указателю на любой объект или функцию. Преобразование нулевого указателя в другой тип указателя дает нулевой указатель этого типа.

Любые два нулевых указателя должны сравниваться как равные.

Однако ваш вопрос интересный. Лично мне неизвестна платформа, которая не использует значение времени выполнения 0 для представления нулевого указателя. Однако стандарт этого не требует, поэтому, если вы можете избежать допущения в своем коде, почему бы и нет?

Меня также заинтересует любой, кто знает систему, которая использует ненулевое значение времени выполнения для нулевой указатель.

1
ответ дан 14 December 2019 в 13:32
поделиться

Стандарт C99 говорит, что когда вы конвертируете целочисленное значение 0 в указатель, оно становится NULL-указателем. Итак, ((char *) 0) является указателем NULL. НУЛЕВОЙ указатель не обязательно должен иметь фактическое двоичное представление 0 . Это может быть, например, 0x12345678 .

Стандарт C также утверждает, что при преобразовании указателя NULL в целочисленную константу результат "определяется реализацией". На самом деле компиляторы просто приводят числовое значение указателя к соответствующему целочисленному значению, как сказал AndreyT. Таким образом, в приведенном выше примере целочисленное значение может оказаться 0x12345678 , хотя технически это может быть что угодно (т. Е. Компилятору разрешено сказать «преобразование NULL-указателя обратно в целочисленное значение приводит к значение 0xDEADBEEF "). Обратите внимание, что это означает, что даже на платформах, где указатель NULL имеет значение 0 , компилятор может преобразовать его в произвольное целочисленное значение при преобразовании. На самом деле, однако, никакие компиляторы этого не делают, потому что это было бы довольно безумно.

Итак, да, стандарт C позволяет многое. В действительности, любая платформа, на которой вы, вероятно, будете работать, будет представлять NULL-указатель как 0 , а преобразование NULL-указателя в целочисленное значение приведет к 0 . Посмотрите здесь (раздел 1.14) для списка некоторых исключений (неясных) архитектур, которые не используют 0 для NULL-указателя.

1
ответ дан 14 December 2019 в 13:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: