Адрес разыменованной указательной конструкции

В библиотеке unqlite c я нашел следующий код:

pObj = jx9VmReserveMemObj(&(*pVm),&nIdx); 

где pVm :

 typedef struct jx9_vm jx9_vm; jx9_vm *pVm 

и вызванная функция объявляется как:

 jx9_value * jx9VmReserveMemObj(jx9_vm *, sxu32 *); 

Что для конструкции &(*pVm) используется в вызове вместо простого pVm ? Is &(*pVm) эквивалентно pVm ?

Цитирование C11 , глава §6.5.3.2, Операторы адреса и косвенности

[…] Если операнд является результатом унарного * оператора, ни этот оператор, ни оператор & не оцениваются, и результат как бы опускался , за исключением того, что ограничения на операторы все еще применяются, а результат не является lvalue. […]

Итак, да , они эквивалентны .

Однако эту конструкцию можно использовать для проверки типа аргумента на тип указателя. Из свойства унарного оператора *

Операнд унарного * оператора должен иметь тип указателя.

Итак, конструкция &(*pVm)

  • будет хорошо, если pvm – имя указателя или массива.
  • будет генерировать ошибку компилятора, если pvm является переменной типа не указателя.

См. Другой ответ Alter Mann для примера кода.

Еще одна разница ( в общем случае ), pVm может быть назначена (может использоваться как LHS оператора присваивания), но &(*pVm) не может.

Is &(*pVm) эквивалентно pVm ?

Да. * 1

То же самое для *(&pVm) .


(* 1) Так как * -оператор ( de-referencing ) применим только к указателям, первая конструкция работает только с указателем (или массивом, который распадается на указатель на его 1-й элемент). Последнее может применяться к любому типу переменной. :

Да, они одинаковы, но заметьте, что это не удается, когда объект не является массивом или указателем:

 #include  struct t { int value; }; typedef struct tt; int func(t *ptr) { return ptr->value; } int main(void) { to = {.value = 0}; tv[2] = {{.value = 1}, {.value = 2}}; printf("%d\n", func(&(*o))); /* error: invalid type argument of unary '*' */ printf("%d\n", func(&(*v))); /* WORKS */ return 0; }