我想编写一个输入数据数组并使用指针输出另一个数据数组的函数。
我想知道src
和dst
都指向同一个地址会导致什么结果,因为我知道编译器可以针对const进行优化。它是未定义的行为吗? (我标记了C和C ++,因为我不确定答案是否可能会有所不同,并且我想了解两者。)
void f(const char *src, char *dst) {
dst[2] = src[0];
dst[1] = src[1];
dst[0] = src[2];
}
int main() {
char s[] = "123";
f(s,s);
printf("%s\n", s);
return 0;
}
除了上面的问题,如果我删除原始代码中的const
,这是否定义明确?
具有和不具有const
限定符的定义良好。
首先要寻找的是严格的别名规则1。如果src
和dst
指向同一对象,则它们必须具有compatible types;否则,它们必须具有char*
。 char const*
和const
兼容。
关于dst == src
限定词,您可能会争辩说,由于当src
您的函数有效地修改了src
指向的内容时,const
不应该被视为const
。这不是const
的工作方式。需要考虑两种情况:
char const data[42];
时,如const
中一样,对其进行修改将导致未定义的行为。char const* pdata = data;
中那样定义了对const
对象的引用或指针,只要未定义为int main()
{
int result = 42;
int const& presult = result;
const_cast<int&>(presult) = 0;
return presult; // 0
}
2(请参见1。),on就可以修改基础对象。因此,以下是明确定义的:What is the strict aliasing rule?
1)Is const_cast
safe?2) const_cast
使您的生活更简单,并使用std::array
。无论如何,这是因为s
本身不是静态的,并且在参数中使用const
意味着“我不会更改此[[在函数体中]”,而不是它必须是const
本身。
也就是说,编译器不能
假定仅由于参数是const T* ptr
,ptr
指向的内存就不会通过另一个指针更改。指针甚至不必相等。 const
是一种义务,而不是保证-您(=该函数)有义务不通过该指针进行更改。为了真正获得保证,您需要使用restrict
关键字标记指针。这是C99的关键字,不幸的是,到目前为止,它还没有引入C ++。但是,许多编译器都支持__restrict
。
Realistic usage of the C99 'restrict' keyword?
关于restrict关键字的使用方式。