Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何初始化堆上结构的常量成员_C - Fatal编程技术网

C 如何初始化堆上结构的常量成员

C 如何初始化堆上结构的常量成员,c,C,我想在堆上分配一个结构,初始化它并从函数返回指向它的指针。我想知道在这种情况下是否有办法初始化结构的常量成员: #include <stdlib.h> typedef struct { const int x; const int y; } ImmutablePoint; ImmutablePoint * make_immutable_point(int x, int y) { ImmutablePoint *p = (ImmutablePoint *)malloc(

我想在堆上分配一个结构,初始化它并从函数返回指向它的指针。我想知道在这种情况下是否有办法初始化结构的常量成员:

#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;
}
#包括
类型定义结构{
常数int x;
const int y;
}不可变点;
不可变点*使不可变点(int x,int y)
{
ImmutablePoint*p=(ImmutablePoint*)malloc(sizeof(ImmutablePoint));
如果(p==NULL)中止();
//如何初始化成员x和y?
返回p;
}
我是否应该由此得出结论,不可能在包含常量成员的堆上分配和初始化结构?

如下:

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++不同,不需要在C中转换<代码> MalOC 的返回值,并且它通常被认为是坏的形式,因为它可以隐藏其他错误)。< /P> < P>如果这是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;
}

如果你坚持在结构中保持常数,你将不得不做一些铸造来绕过它:

int *cheat_x = (int *)&p->x;
*cheat_x = 3;
我喜欢,但我也想到了这一点

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;
}

请注意,init初始化中使用的.x和.y是C99,如果编译器不支持,您当然可以使用未修改的条目。标准说明:(6.7.3)如果试图通过使用左值和非常量限定类型来修改由常量限定类型定义的对象,则行为是未定义的。在undefined Behavior(未定义行为)部分:尝试通过使用左值和非常量限定类型(6.7.3),修改使用常量限定类型定义的对象。这将使这个例子展示ub。您的看法是什么?@self.:这里返回的指针指向的对象实际上从未定义过,因为它是由
malloc()
创建的。认为<代码> P<代码>也可以定义为<代码> VATP*;code>相反,当
sizeof*p
的两个实例都更改为
sizeof init
@Ephemera:是的,它可以-x86-64上的gcc使用最低级别的优化将上述函数编译成一个不调用
memcpy()
的函数。也就是说,一旦调用
malloc()
memcpy()
就不太可能是个问题。@kevinarpe:这没关系,因为
sizeof
显式地不计算它的参数,所以表达式的行为仍然是定义的。这不会调用未定义的行为吗?如果分配内存,我认为这很好。如果这是C,则对
malloc
的返回值进行强制转换是不必要的,也是多余的。对不起,我在这里没有看到常量。你能解释一下吗?@KCArpe:我分配并分配了一个结构与
ImmutablePoint
相同但可变的
struct
,然后在return语句中强制转换指针,以便用户永远看不到可变版本。这是一个相当标准的滥用铸造“打破”类型系统。这个相对caf的解决方案的缺点是它不是:如果有人编辑
不可变点
,我也需要编辑
不可变点
尽管编译器也允许使它们不同。