【问题标题】:Assigning values to constant member of dynamically allocated struct during initialization [duplicate]在初始化期间将值分配给动态分配的结构的常量成员[重复]
【发布时间】:2020-09-28 06:10:24
【问题描述】:

我有一个点结构:

struct Point 
{
    const int x; 
    const int y;
};

在我的代码中,我有很多这样的点,所以我想创建指向它们的指针,这样我在处理它们时就不会看到它们被一遍又一遍地复制。

知道您可以像这样初始化结构的常量成员:

struct Point my_point = { .x = 1, .y = 2};

我认为我可以对动态分配的结构做同样的事情。但似乎并非如此:

struct Point *point = malloc(sizeof(struct Point));

*point = (struct Point){.x = 1, .y = 2}; 

但是我得到了

main.c: In function ‘main’:
main.c:23:8: error: assignment of read-only location ‘*point’
 *point = (struct Point){.x = 1, .y = 2};

使用 GCC 7.1.1 时。在铿锵声中,我得到了

prog.c:23:8: error: cannot assign to lvalue with const-qualified data member 'x'
*point = (struct Point){.x = 1, .y = 2}; 
~~~~~~ ^
prog.c:14:15: note: data member 'x' declared const here
    const int x; 
    ~~~~~~~~~~^
prog.c:15:15: note: data member 'y' declared const here
    const int y;
    ~~~~~~~~~~^
1 error generated.

有没有办法做到这一点?

例子

#include <stdio.h>
#include <stdlib.h>

struct Point 
{
    const int x; 
    const int y;
};


int main()
{
    struct Point *point = malloc(sizeof(struct Point));

    *point = (struct Point){.x = 1, .y = 2}; 
    return 0;
}

【问题讨论】:

  • 为什么xy 需要只读?
  • @JHBonarius 只是方便。我想向查看它的人发出信号,这些值预计不会更改(它们是从文件中加载的,因此无论如何在我的应用程序中更改它们是没有意义的)。

标签: c pointers


【解决方案1】:

我真的找不到解决这个问题的好方法。在 C++ 中,您可以使用构造函数和私有成员来解决这个问题。

但你可以使用memcpywhich is safe

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Point {
    const int x; 
    const int y;
};

int main(void){
    struct Point *p = malloc(sizeof *p);
    memcpy(p, &(struct Point) {.x=1, .y=2 }, sizeof *p);

    printf("%d %d\n", (*p).x, (*p).y);
}

可以为此使用变量:

int x=1; int y=2;
memcpy(p, &(struct Point) {.x=x, .y=y }, sizeof *p);

如果您使用gcc,您可以使用编译器扩展:

memcpy(p, &(typeof(*p)) {.x=1, .y=2 }, sizeof *p);

但我确实希望在大多数情况下以下方法会更好:

struct Point 
{
    int x; // Remove const here
    int y;
};

int main(void) 
{
    // Allocate and assign a non const object
    struct Point *tmp_ptr = malloc(sizeof *tmp_ptr);
    *tmp_ptr = (struct Point) {.x=1, .y=2};

    // Create a new const pointer
    const struct Point *p = tmp_ptr;

    // This will invoke compiler error
    (*p).x = 42;
}

【讨论】:

  • 不确定 memcpy 是否提供明确定义的行为。我认为它会使存储在内存中的内容的“有效类型”非常量,并可能导致 UB 打嗝。我必须仔细检查标准中有关有效类型的所有语言律师资料以确保确定。
  • @Lundin 请做
  • @Lundin 你可以在这里写下你的发现:stackoverflow.com/q/64098563/6699433
  • @Lundin 实际上,this question 对于这个和我的问题来说似乎都是一个不错的选择
  • 在那里发布了答案。 stackoverflow.com/a/64100088/584518。我相信接受的答案是正确的,但它并没有深入到肮脏的细节。
【解决方案2】:

最好的解决方案是对整个结构进行 const 限定,而不是单个成员。您可以将分配和初始化包装在一个“构造函数”中,它返回一个只读指针:

typedef struct
{
  int x; 
  int y;
} point_t;

const point_t* point_create (void)
{
  point_t* obj = malloc(sizeof *obj);
  if(obj == NULL)
    return NULL;
  
  *obj = (point_t){.x = 1, .y = 2};
  return obj;
}

【讨论】:

    猜你喜欢
    • 2015-07-23
    • 2020-12-17
    • 1970-01-01
    • 1970-01-01
    • 2020-08-21
    • 2012-07-18
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多