如何在C中的结构中初始化常量(使用malloc)
我试过了如何在C中的结构中初始化常量(使用malloc),c,struct,initialization,malloc,constants,C,Struct,Initialization,Malloc,Constants,我试过了 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:
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
gereksiz.c:10:5: error: assignment of read-only member 'a'
gereksiz.c:11:5: error: assignment of read-only member 'b'
还有这个,
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:3:17: error: expected ':', ',', ';', '}' or '__attribute__' before '=' token
gereksiz.c:10:5: error: assignment of read-only member 'a'
gereksiz.c:11:5: error: assignment of read-only member 'b'
两个都没有被编译。在使用malloc分配内存时,有没有办法初始化结构内部的常量变量?您需要丢弃常量来初始化malloc结构的字段:
struct deneme *mydeneme = malloc(sizeof(struct deneme));
*(int *)&mydeneme->a = 15;
*(int *)&mydeneme->b = 20;
或者,您可以创建结构的初始化版本,并使用它进行memcpy:
struct deneme deneme_init = { 15, 20 };
struct deneme *mydeneme = malloc(sizeof(struct deneme));
memcpy(mydeneme, &deneme_init, sizeof(struct deneme));
如果您经常这样做,您可以使deneme\u init
静态和/或全局(因此只需要构建一次)
使用C11标准参考资料,解释为什么该代码不是某些注释所建议的未定义行为:
- 此代码不违反6.7.3/6,因为
返回的空格不是“定义了常量限定类型的对象”。表达式malloc
不是一个对象,它是一个表达式。尽管它有mydeneme->a
-qualified类型,但它表示一个没有用const限定类型定义的对象(实际上,根本没有用任何类型定义)const
- 写入
分配的空间不会违反严格的别名规则,因为每次写入都会更新有效类型(6.5/6)malloc
malloc
分配的空间读取数据可能会违反严格的别名规则)
在Chris的代码示例中,第一个示例将整数值的有效类型设置为
int
,第二个示例将有效类型设置为const int
,但是在这两种情况下,通过*mydeneme
读取这些值是正确的,因为严格的别名规则(6.5/7 bullet 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;
}
我还没有测试过,但是代码似乎是正确的有趣的是,我发现这种C99方式在clang中工作,但在gcc中不工作
int main(int argc, const char *argv[])
{
struct deneme *pmydeneme = malloc(sizeof(struct deneme));
*pmydeneme = (struct deneme) {15, 20};
return 0;
}
我不同意基督多德的回答,因为我认为他的解决方案根据标准给出了未定义的行为,正如其他人所说
为了以不调用未定义行为的方式“绕过”const
限定符,我提出以下解决方案:
malloc()调用初始化的void*
变量李>
定义所需类型的对象,在本例中为struct deneme
,并以某种方式初始化它,使const
限定符不会抱怨(即在声明行本身中)李>
使用memcpy()
将struct deneme
对象的位复制到void*
对象李>
声明指向struct deneme
对象的指针,并将其初始化为(void*)
变量,该变量以前强制转换为(struct deneme*)
李>
因此,我的代码是:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct deneme {
const int a;
const int b;
};
struct deneme* deneme_init(struct deneme data) {
void *x = malloc(sizeof(struct deneme));
memcpy(x, &data, sizeof(struct deneme));
return (struct deneme*) x;
}
int main(void) {
struct deneme *obj = deneme_init((struct deneme) { 15, 20, } );
printf("obj->a: %d, obj->b: %d.\n", obj->a, obj->b);
return 0;
}
#包括
#包括
#包括
致密结构{
常数INTA;
常数int b;
};
结构deneme*deneme_init(结构deneme数据){
void*x=malloc(sizeof(struct deneme));
memcpy(x,&data,sizeof(struct deneme));
返回(struct deneme*)x;
}
内部主(空){
结构deneme*obj=deneme_init((结构deneme){15,20,});
printf(“obj->a:%d,obj->b:%d.\n”,obj->a,obj->b);
返回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;
理由:
在深入研究这个问题时,首先需要确定的是,所谓的左值是否有一个类型,如果是,那么该类型是否带有限定符。这在C11 6.3.2.1/1中定义:
左值是一个表达式(对象类型不是void),它可能
指定一个对象;如果左值在求值时未指定对象,则行为未定义。当一个对象被称为具有特定类型时,该类型由用于指定该对象的左值指定。可修改左值是一个左值,它不具有数组类型、不完整类型、不具有constqualified类型,并且如果它是结构或联合,则不具有任何具有constqualified类型的成员(递归地包括所有包含的聚合或联合的任何成员或元素)
显然,左值不仅有类型,还有限定符。如果它是const限定的,或者如果它是具有const限定成员的结构,则它不是可修改的左值
继续讨论“严格别名”和有效类型的规则,C11 6.5/7:
访问其存储值的对象的有效类型是对象的声明类型(如果有)。87)如果通过
如果左值的类型不是字符类型,则左值的类型将成为
该访问和不修改的后续访问的有效对象类型
存储的值。如果使用将值复制到没有声明类型的对象中
memcpy
或memmove
,或作为字符类型数组复制,然后是有效类型
对于该访问和不修改
值是从中复制值的对象的有效类型(如果有)。对于
对没有声明类型的对象的所有其他访问,对象的有效类型为
只是用于访问的左值的类型
分配的对象没有声明的类型
这意味着分配的c