#include <stdio.h>
#include <stdlib.h>
const int * func()
{
int * i = malloc(sizeof(int));
(*i) = 5; // initialize the value of the memory area
return i;
}
int main()
{
int * p = func();
printf("%d\n", (*p));
(*p) = 3; // attempt to change the memory area - compiles fine
printf("%d\n", (*p));
free(p);
return 0;
}
为什么即使(*p)
返回一个const指针,编译器也允许我更改func()
?
我正在使用gcc,它只在int * p = func();
行显示警告:“警告:初始化会丢弃指针目标类型的限定符”。
感谢。
答案 0 :(得分:4)
您的计划无效。 C禁止隐式删除const
之类的内容,并且符合规范GCC应至少为您提供该代码的警告。您需要使用强制转换来移除const
。
已经消除了警告,但是你可以依赖程序来工作(虽然从标准的角度来看不再这样),因为指针指向malloc的内存区域。你可以写信给那个地区。指向某个内存的const T*
并不意味着此后内存标记为不可变。
请注意,标准不要求编译器拒绝任何程序。标准仅要求编译器有时向用户发出消息。无论是错误消息或警告,消息是如何发出的以及发射后发生的事情,标准都没有规定。
答案 1 :(得分:3)
编译器和C语言“允许”你做各种愚蠢的事情,特别是如果你忽略警告。将const int*
转换为int*
是编译器可以检测到此处存在任何错误的唯一点,并且它会针对该转换发出警告。这就像你得到的一样多,这也是你不应该忽视警告的原因。
由于定义了这个程序的行为(通过GCC,就像你明确地转换为const int*
一样),所以你所做的事情至少可能是你想要的做。这就是代码被接受的原因。
答案 2 :(得分:1)
您正在将const
指针转换为普通指针,这实际上允许您更改指针。你通过返回一个常量指针打破你所做的“契约”,但由于C是一种弱类型语言,因此它在语法上是合法的。
基本上GCC正在帮助你。从语法上讲,将const
指针转换为常规指针是合法的,但您可能不希望这样做,因此GCC会发出警告。
答案 3 :(得分:0)
首先,内存在main中是有效的,因为它存储在堆上并且没有被销毁/释放。所以编译器只是向你发出警告。
如果您尝试
const int * p = func();
然后当然(*p) = 3
将是错误。