TL; DR: Большая часть того, о чем вы спрашиваете, относится к поведению, зависящему от реализации, и языковым расширениям. Обратитесь к документации по вашему компилятору, если у вас есть реальная потребность в таком поведении.
- в
void *p = 0
, есть ли неявное преобразование из 0
в void*
?
Инициализация не соответствует, но многие компиляторы принимают ее как расширение. Те, которые определяют результат так, как они хотят, но на практике они действительно обеспечивают неявное преобразование в void *
.
Поскольку литерал 0
является «константой нулевого указателя», потому что инициализаторы выполняют те же преобразования, что и простое присваивание, и потому что простое присваивание имеет специальное положение для назначения констант пустых указателей указателям, да, 0
неявно преобразуется в тип void *
. Кроме того, поскольку 0
является константой нулевого указателя, такое преобразование приводит к нулевому указателю типа void *
.
Является ли неявное преобразование таким же, как явное преобразование (void *)0
, т. Е. void *p = 0
совпадает с void *p = (void*) 0
?
Есть веская причина ожидать, что компилятор, который принимает первую форму, будет обрабатывать ее точно так же, как и последняя форма, но, опять же, первая не соответствует, и реализации, которые принимают ее как расширение, определяют их собственная семантика для него.
Да. В C нигде не проводится различия между эффектами конверсий, указанными явно посредством приведения, и автоматическими конверсиями между одними и теми же типами.
Производит ли void *p = (void*) 0
указатель на физический или виртуальный адрес 0 или нулевой указатель void
?
Инициализирует p
, чтобы содержать нулевой указатель (типа void *
). Согласно C, нулевой указатель не указывает на какой-либо объект, и C не имеет смысла в адресах, кроме адресов объектов или функций, поэтому по крайней мере в этом смысле неверно интерпретировать такой указатель как указывающий на какой-либо конкретный адрес. Эффект разыменования такого указателя не определяется C, но он может быть определен некоторыми реализациями - возможно, для попытки получить доступ к объекту по адресу 0.
- Если я использую ненулевой номер, например,
void *p = 123
, есть ли неявное преобразование из 123
в void *
?
Эта инициализация не соответствует, но некоторые компиляторы предоставляют неявное преобразование как расширение.
Является ли неявное преобразование таким же, как явное преобразование (void *) 123
?
Существует очень веская причина ожидать, что это будет иметь место с компилятором, который вообще реализует такое неявное преобразование, но, опять же, "расширение".
void *p = 123
или void *p = (void *)123
сделает p
указателем на физический или виртуальный адрес 123
?
Это определяется реализацией. Опять же, C не имеет смысла адресов, кроме адресов объектов или функций, и, в частности, он сам отказывается указывать результат преобразования целого числа в тип указателя, за исключением целых чисел, полученных путем преобразования указателя в целое число в первую очередь, и для целочисленных константных выражений со значением 0.
Однако в некоторых реализациях преобразование целого числа (кроме целочисленной константы со значением 0) в указатель приводит к интерпретации целого числа как адреса и преобразованию в указатель на этот адрес, как если бы объект с этим адресом. В размещенной реализации C это обычно будет виртуальный адрес. В автономной реализации это обычно будет физический адрес. Некоторые из реализаций могут распространять это поведение также на целочисленные константы со значением 0, которые могут быть или не быть изначально несоответствующими.
Если void *p = (void *)123
не может сгенерировать указатель на физический или виртуальный адрес 123
, может int addr = 123; void *p = (void *)addr;
? Я создаю его, заменив unitptr_t
на int в первом примере в цитате.
Есть все основания ожидать, что результат явного преобразования переменной int
со значением 123 точно такой же, как и при явном преобразовании целочисленной константы со значением 123, но, технически, определение этой реализации может привести к комната для соответствующих компиляторов.