如何在C中的结构中初始化const(使用malloc)[英] How to initialize const in a struct in C (with malloc)

本文是小编为大家收集整理的关于如何在C中的结构中初始化const(使用malloc)的处理方法,想解了如何在C中的结构中初始化const(使用malloc)的问题怎么解决?如何在C中的结构中初始化const(使用malloc)问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

我尝试过;

void *malloc(unsigned int);
struct deneme {
    const int a = 15;
    const int b = 16;
};

int main(int argc, const char *argv[])
{
    struct deneme *mydeneme = malloc(sizeof(struct deneme));
    return 0;
}

这是编译器的错误:

gereksiz.c:3:17: error: expected ':', ',', ';', '}' or '__attribute__' before '=' token

,也是这个;

void *malloc(unsigned int);
struct deneme {
    const int a;
    const int b;
};

int main(int argc, const char *argv[])
{
    struct deneme *mydeneme = malloc(sizeof(struct deneme));
    mydeneme->a = 15;
    mydeneme->b = 20;
    return 0;
}

这是编译器的错误:

gereksiz.c:10:5: error: assignment of read-only member 'a'
gereksiz.c:11:5: error: assignment of read-only member 'b'

,都没有被编译.当用malloc分配内存时,有什么方法可以在结构内部初始化const变量?

推荐答案

您需要抛弃const以初始化malloc'ed结构的字段:

struct deneme *mydeneme = malloc(sizeof(struct deneme));
*(int *)&mydeneme->a = 15;
*(int *)&mydeneme->b = 20;

另外,您可以创建struct的初始化版本并memcpy it:

struct deneme deneme_init = { 15, 20 };
struct deneme *mydeneme = malloc(sizeof(struct deneme));
memcpy(mydeneme, &deneme_init, sizeof(struct deneme));

如果您经常这样做,则可以制作deneme_init静态和/或全局(因此只需要一次构建一次).


使用C11标准参考文献:

,解释了为什么该代码不是未定义的行为:

  • 此代码不违反6.7.3/6,因为malloc返回的空间不是"对象定义的具有const-fequ-fequififified类型".表达式mydeneme->a不是对象,而是表达式.尽管它具有const合格类型,但它表示一个未定义的对象,该对象(实际上,根本没有使用任何类型定义).

  • 严格的混叠规则永远不会通过写入malloc分配的空间而违反,因为有效的类型(6.5/6)都会通过每个写作更新.

    .

(严格的混叠规则可以通过从malloc分配的空间中阅读来违反).

在克里斯的代码示例中,第一个将整数的有效类型设置为int,第二个将有效类型设置为const int,但是在这两种情况下,都可以通过是正确的,因为严格确定的规则(6.5/7子弹2)允许通过表达式读取对象,该表达式比对象的有效类型具有相同或更合格的表达式.由于表达式mydeneme->a具有类型const int,因此可以用于读取有效类型int和const int的对象.

其他推荐答案

您是否尝试过这样做:

int main(int argc, const char *argv[])
{
    struct deneme mydeneme = { 15, 20 };
    struct deneme *pmydeneme = malloc(sizeof(struct deneme));
    memcpy(pmydeneme, &mydeneme , sizeof(mydeneme));
    return 0;
}

我尚未测试,但代码似乎正确

其他推荐答案

要扩展@chris Dodd的答案,我一直在阅读标准的"语言律师"详细信息,看来此代码定义很好:

struct deneme deneme_init = { 15, 20 };
struct deneme *mydeneme = malloc(sizeof(struct deneme));
memcpy(mydeneme, &deneme_init, sizeof(struct deneme));

另外,动态创建一个已有验证的完整结构对象:

const struct deneme deneme_init = { 15, 20 };
struct deneme *mydeneme = malloc(sizeof(struct deneme));
memcpy(mydeneme, &deneme_init, sizeof(struct deneme));

const struct deneme *read_only = mydeneme; 

理由:

到达最底层时需要确定的第一件事是,如果所谓的 lvalue 具有类型,如果是这样,那么该类型是否带有限定词.这是在C11 6.3.2.1/1中定义的:

an lvalue 是一种表达式(除void以外的对象类型) 指定对象;如果在评估对象时未指定该对象,则行为是不确定的.当对象被认为具有特定类型时,该类型是由用于指定对象的LVALUE指定的. A 可修改的lvalue 是一个没有数组类型,没有不完整类型的LVALUE,没有构造类型,如果它是结构或联合,则没有任何成员(包括,递归地,所有包含的骨料或工会的任何成员或元素都具有构造类型.

很明显,lvalue不仅具有类型,而且还有预选赛.如果它是合格的,则不是可修改的lvalue,或者它是具有合理成员的结构.

继续遵守"严格混叠"和有效类型,C11 6.5/7:

有效的对象的访问访问值的对象是对象的声明类型,如果有的话. 87)如果将值存储在一个对象没有通过 LVALUE具有不是字符类型的类型,然后LVALUE的类型变为 该访问的对象的有效类型以及未修改的后续访问 存储的值.如果将值复制到没有声明类型的对象中,则使用 memcpy或memmove,或被复制为字符类型,然后是有效类型 该访问的修改对象以及未修改的后续访问 值是复制该值的有效类型,如果它具有一个值.为了 所有其他访问没有声明类型的对象的所有其他访问,对象的有效类型是 仅仅是用于访问的LVALUE的类型.

  1. 分配的对象没有声明类型.

这意味着Malloc返回的分配块没有有效的类型,直到通过lvalue写入访问(通过分配或memcpy)存储在该内存位置内部的某些东西.然后,它获得了该写入访问中使用的有效类型.

值得注意的是,指向该内存位置的指针的类型是完全无关紧要的.它也可能是volatile bananas_t*,因为它还没有用于访问LVALUE(至少尚未使用). 仅用于LVALUE访问的类型很重要.

现在,这就是它变得模糊的地方:是否通过可修改的lvalue完成此写入访问可能至关重要.上述有效类型的规则不提及限定符和"严格的混叠规则",因此不在乎对象是否合格(" type " May olias"类型",反之亦然).

但是在其他情况下,有效类型是否仅读取可能重要:最著名的是,如果我们后来尝试对有效类型具有const const const的对象进行不合格的LVALUE访问. (C11 6.7.3/6"如果尝试通过使用具有非符合条件的类型的LVALUE来修改用constemified类型定义的对象,则行为是未定义的.") lvalues,即使标准没有明确提及的有效类型,有效类型也有意义.

因此,绝对可以肯定,我们必须正确使用该类型用于LVALUE访问权限.如果整个对象是仅读取的,则应使用此帖子顶部的第二个摘要.否则,如果它被读/写(但可能与合格的成员一起使用),则应使用第一个片段.然后,无论您如何阅读标准,都永远不会出错.

本文地址:https://www.itbaoku.cn/post/359160.html