如何在C中初始化堆中的只读内存位置?
考虑以下代码:如何在C中初始化堆中的只读内存位置?,c,C,考虑以下代码: #include<stdio.h> int main() { const char* c = malloc(1); *c = 'a'; printf("%c\n",*c); } 如何在堆内存中初始化常量变量?堆中没有只读位置。请参见Steve Summents的答案,以获得良好的解释 无论你做什么来实现这一点,都要由你来确保你不会在这些地方写作。你可以很好地保护自己,但不是100% 你可以这样做: char * x = malloc(1);
#include<stdio.h>
int main()
{
const char* c = malloc(1);
*c = 'a';
printf("%c\n",*c);
}
如何在堆内存中初始化常量变量?堆中没有只读位置。请参见Steve Summents的答案,以获得良好的解释 无论你做什么来实现这一点,都要由你来确保你不会在这些地方写作。你可以很好地保护自己,但不是100% 你可以这样做:
char * x = malloc(1);
*x = 'a';
const char * c = x;
// Promise to not use the pointer x again
printf("%c\n",*c);
或者,如果您更愿意将其封装一点:
const char * init()
{
char* c = malloc(1);
if(c == NULL) { // Always check if allocation is successful
// Code for error handling
}
*c = 'a';
return c;
}
int main()
{
const char * p = init();
printf("%c\n",*p);
}
请注意,仍然允许在不使用常量的情况下写入char*p=init()
,这样确实可以写入*p='a'
,但您至少会触发此警告:
warning: initialization discards ‘const’ qualifier from pointer target
type [-Wdiscarded-qualifiers]
char * p = init();
这里需要注意的另一件事是,如果调用free(p)
,您将收到警告,因为p
是一个const
指针。如果您将p
声明为一个char*
,您将摆脱此警告,但您将得到我在上一段中提到的警告。(当然,通过将其声明为const,您也将失去所有试图获得的写保护)
要解决这个问题,您可以使用free((char*)p)
作为旁注,如果您想确保永远不会更改
p
指向的位置,那么可以像这样声明const char*const p=init()
。这样就不可能使p
指向代码后面的其他内容。堆中没有只读位置。请参见Steve Summents的答案,以获得良好的解释
无论你做什么来实现这一点,都要由你来确保你不会在这些地方写作。你可以很好地保护自己,但不是100%
你可以这样做:
char * x = malloc(1);
*x = 'a';
const char * c = x;
// Promise to not use the pointer x again
printf("%c\n",*c);
或者,如果您更愿意将其封装一点:
const char * init()
{
char* c = malloc(1);
if(c == NULL) { // Always check if allocation is successful
// Code for error handling
}
*c = 'a';
return c;
}
int main()
{
const char * p = init();
printf("%c\n",*p);
}
请注意,仍然允许在不使用常量的情况下写入char*p=init()
,这样确实可以写入*p='a'
,但您至少会触发此警告:
warning: initialization discards ‘const’ qualifier from pointer target
type [-Wdiscarded-qualifiers]
char * p = init();
这里需要注意的另一件事是,如果调用free(p)
,您将收到警告,因为p
是一个const
指针。如果您将p
声明为一个char*
,您将摆脱此警告,但您将得到我在上一段中提到的警告。(当然,通过将其声明为const,您也将失去所有试图获得的写保护)
要解决这个问题,您可以使用free((char*)p)
作为旁注,如果您想确保永远不会更改
p
指向的位置,那么可以像这样声明const char*const p=init()
。这就不可能让p
指向代码后面的其他内容。首先,要明白,堆中没有“只读位置”这样的东西。堆是100%可写的malloc()
定义为返回void*
。允许您写入malloc
返回的指针指向的数据
但是第二件要理解的事情是,const
也不一定意味着“只读”
只读内存是一种东西,它通常会被const
指针指向,如果(尽管有任何const
指针)您试图写入只读内存,通常会出现某种异常
但是您可以拥有由非const
指针指向的只读内存,也可以拥有指向可写内存的const
指针
因此,const
真正的意思是“我保证不写入此内存”或“我声明我不打算写入此内存”,并附加规定“如果我不小心尝试写入此内存,我希望编译器给我编译时错误。”
如果您有一个普通的const
指针,您可以初始化它一次。你可以这样说
const str1[] = "hello";
及
即使以后尝试更新字符串,如
*str1 = 'x'; /* WRONG */
或
这将失败。(您可以将其视为const
限定数据的“初始化异常”
但正如您所发现的,通过调用
malloc
初始化的const
指针没有例外。如果您想从malloc
中获取一些内存,并初始化一次,然后保证以后不修改它,并且如果您想让编译器为您强制执行此承诺,您不能这样做首先,除非您使用注释和中描述的双指针解决方法,否则请理解“堆中没有只读位置”。堆是100%可写的。malloc()
定义为返回void*
。允许您写入malloc
返回的指针指向的数据
但是第二件要理解的事情是,const
也不一定意味着“只读”
只读内存是一种东西,它通常会被const
指针指向,如果(尽管有任何const
指针)您试图写入只读内存,通常会出现某种异常
但是您可以拥有由非const
指针指向的只读内存,也可以拥有指向可写内存的const
指针
因此,const
真正的意思是“我保证不写入此内存”或“我声明我不打算写入此内存”,并附加规定“如果我不小心尝试写入此内存,我希望编译器给我编译时错误。”
如果你有一个序号