C - 通过别名非常量指针修改const

时间:2015-09-22 01:28:14

标签: c const compiler-optimization

在标准C中是否允许函数使用别名int修改const int *给定为int *?换句话说,以下代码是否保证始终在标准C中返回42和1?

#include <stdio.h>

void foo(const int *a, int *b)
{
    printf("%d\n", *a);
    *b = 1;
    printf("%d\n", *a);
}

int main(void)
{
    int a = 42;
    foo(&a, &a);
    return 0;
}

4 个答案:

答案 0 :(得分:5)

在您的示例代码中,您有一个整数。你接受一个const指针,以及一个指向它的非const指针。当然,通过非const指针修改整数是合法且定义明确的。

由于两个指针都是指向整数的指针,并且const指针不需要指向const对象,因此编译器应该期望从const指针读取的值可以已经改变,并且是必需的重新加载价值。

请注意,如果您使用了restrict关键字,则不会出现这种情况,因为它指定指针参数不会对任何其他指针参数进行别名,因此编译器可以优化重新加载。

答案 1 :(得分:1)

是的,是的。您的程序已定义。

指向带有指向const int的指针的非const int变量这一事实不会使该变量成为const,并且仍然可以通过指向int的指针或使用原始变量标签进行修改。 / p>

答案 2 :(得分:0)

是的,你可以这样做(如果你知道你可以逃脱它)。

您可能无法逃脱的一个原因是,如果您要写入的目标内存位于只读受保护区域(例如常量数据),那么您将获得访问冲突。例如,编译时的任何const都以可执行文件的只读数据部分结束。大多数平台都支持保护它免于在运行时写入。

基本上不要这样做。

您的示例还有其他问题可能无法使其成为最佳演示。如需要在第二个printf中重新加载* a,编译器可能会优化它! (它知道'a'没有改变,它知道'a'指向const,因此,它不需要通过为第二个'* a'表达式执行内存加载来重新加载内存,它可以重用它可能的值从第一次加载'* a'开始就有一个寄存器。现在如果你在它们之间添加一个内存屏障,那么你的例子就有可能更好地工作。

https://en.wikipedia.org/wiki/Memory_barrier GCC? asm volatile(“”:::“memory”); //可能在第二次printf之前工作

但你问的实际问题的校长,是的,如果你知道你在做其他类似的事情,你可以这样做。

答案 3 :(得分:-1)

是的,保证始终打印42和1。

const int *a表示指向的值是指针a的常量。

尝试从函数中a*a = 10;)取消引用,您将收到错误。

然而,指针a不是常数。例如,你可以a = b

b可以指向与a相同的地址和/或修改值,就像您在示例中所做的那样。 您是否会将b指针的值声明为常量(const int *b),您会收到错误。

我试着记住这样:

const int *a - 指向int类型的对象,不允许修改(指向该对象的任何其他指针可以执行它想要的操作,取决于其声明/定义)。