Доступ к переменным в структуре из пустого указателя - PullRequest
0 голосов
/ 27 июня 2018

Мне было интересно, есть ли способ доступа к элементу данных в пределах struct, на который указывает void*? Надеюсь, то, что я пытаюсь объяснить, будет более очевидно в моем примере кода:

int main()
{
  struct S
  {
    int val;
  };
  S s;
  s.val = 5;

  void* p;
  p = malloc(sizeof(S));
  *(struct S*) p = s;
  std::cout<< *(struct S*)p.val << std::endl;

}

Я запустил этот точный код приведения p как *(int*)p, и он распечатался нормально, однако использование точного кода выше приводит к ошибке компиляции. Не удалось найти пример, который вполне выполняет эту задачу. Можно ли получить доступ к элементам данных struct после его приведения? Почему или почему нет? если да, то как?

1 Ответ

0 голосов
/ 27 июня 2018

Оператор . имеет более высокий приоритет , чем приведение в стиле C. Таким образом, *(struct S*)p.val рассматривается как *((struct S*)(p.val)), что не имеет смысла, поскольку p является указателем и не имеет членов.

Таким образом, вам нужно скобки, чтобы указать, что вы хотели:

std::cout<< (*(struct S*)p).val << std::endl;

Или, что эквивалентно,

std::cout<< static_cast<S*>(p)->val << std::endl;

[Но также: оператор *(struct S*) p = s; технически имеет неопределенное поведение, даже если все большинство реализаций позволят это. Это связано с тем, что в C ++ есть правила о том, когда создается объект, и ранее по этому адресу не было объекта типа S, а присваивание не создает объект, за исключением некоторых случаев, в которых участвуют члены объединения. Подобное утверждение, у которого нет этой проблемы, было бы new(p) S{s};.

Также также: использование malloc или void* обычно не очень хорошая идея для C ++. malloc следует использовать только при взаимодействии с библиотекой C, которая этого требует. Все, для чего void* кажется полезным, может быть сделано более безопасно с использованием шаблонов. В некоторых случаях void* может быть единственным способом что-то сделать или «умно» избежать дублирования кода или чего-то еще, но все равно использовать его экономно и всегда с особой осторожностью.]

...