C函数返回分配给nonconst指针的const指针 - 警告不是错误

时间:2011-07-24 14:12:33

标签: c function pointers return-type

#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();行显示警告:“警告:初始化会丢弃指针目标类型的限定符”。

感谢。

4 个答案:

答案 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会发出警告。

阅读design by contract

答案 3 :(得分:0)

首先,内存在main中是有效的,因为它存储在堆上并且没有被销毁/释放。所以编译器只是向你发出警告。

如果您尝试

const int * p = func();

然后当然(*p) = 3将是错误。