Как инициализировать const членов структур в куче - PullRequest
38 голосов
/ 08 февраля 2010

Я хотел бы выделить структуру в куче, инициализировать ее и вернуть указатель на нее из функции. Мне интересно, есть ли способ инициализировать константные члены структуры в этом сценарии:

#include <stdlib.h>

typedef struct {
  const int x;
  const int y;
} ImmutablePoint;

ImmutablePoint * make_immutable_point(int x, int y)
{
  ImmutablePoint *p = (ImmutablePoint *)malloc(sizeof(ImmutablePoint));
  if (p == NULL) abort();
  // How to initialize members x and y?
  return p;
}

Следует ли из этого сделать вывод, что невозможно выделить и инициализировать структуру в куче, которая содержит константные члены?

Ответы [ 4 ]

54 голосов
/ 08 февраля 2010

Вроде так:

ImmutablePoint *make_immutable_point(int x, int y)
{
  ImmutablePoint init = { .x = x, .y = y };
  ImmutablePoint *p = malloc(sizeof *p);

  if (p == NULL) abort();
  memcpy(p, &init, sizeof *p);

  return p;
}

(Обратите внимание, что в отличие от C ++ нет необходимости приводить возвращаемое значение malloc в C, и его часто считают плохим тоном, поскольку он может скрывать другие ошибки).

11 голосов
/ 08 февраля 2010

Если это C, а не C ++, я не вижу другого решения, кроме как подорвать систему типов.

ImmutablePoint * make_immutable_point(int x, int y)
{
  ImmutablePoint *p = malloc(sizeof(ImmutablePoint));
  if (p == NULL) abort();

  // this 
  ImmutablePoint temp = {x, y};
  memcpy(p, &temp, sizeof(temp));

  // or this
  *(int*)&p->x = x;
  *(int*)&p->y = y;

  return p;
}
2 голосов
/ 08 февраля 2010

Если вы настаиваете на сохранении константы в структуре, вам придется выполнить какое-то кастинг, чтобы обойти это:

int *cheat_x = (int *)&p->x;
*cheat_x = 3;
1 голос
/ 08 февраля 2010

Мне нравится подход кафе , но это произошло и со мной

ImmutablePoint* newImmutablePoint(int x, int y){ 
   struct unconstpoint {
      int x;
      int y;
   } *p = malloc(sizeof(struct unconstpoint));
   if (p) { // guard against malloc failure
      *p.x = x;
      *p.y = y;
   }
   return (ImmutablePoint*)p;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...