在标准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;
}
答案 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类型的对象,不允许修改(指向该对象的任何其他指针可以执行它想要的操作,取决于其声明/定义)。