使用指向非常數的指針和指向相同地址的常量參數的指針的函數調用 [英] Function call with pointer to non-const and pointer to const arguments of same address
本文介紹了使用指向非常數的指針和指向相同地址的常量參數的指針的函數調用的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我要編寫一個函數,該函數使用指針輸入一個數據數組并輸出另一個數據數組。
我想知道,如果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
", s);
return 0;
}
除了上面的問題,如果我刪除原始代碼中的const
,這個定義是否明確?
推薦答案
雖然行為確實定義良好-但編譯器可以在您所指的意義上針對常量進行優化,這并不是。
也就是說,不允許假設只因為一個參數是const T* ptr
,ptr
指向的內存不會通過另一個指針更改。指針甚至不一定要相等。const
是一種義務,而不是保證-您(=函數)不通過指針進行更改義務。
restrict
關鍵字標記指針。因此,如果您編譯這兩個函數:
int foo(const int* x, int* y) {
int result = *x;
(*y)++;
return result + *x;
}
int bar(const int* x, int* restrict y) {
int result = *x;
(*y)++;
return result + *x;
}
foo()
函數必須從x
讀取兩次,而bar()
只需讀取一次:
foo:
mov eax, DWORD PTR [rdi]
add DWORD PTR [rsi], 1
add eax, DWORD PTR [rdi] # second read
ret
bar:
mov eax, DWORD PTR [rdi]
add DWORD PTR [rsi], 1
add eax, eax # no second read
ret
觀看直播GodBolt。
restrict
只是C中的一個關鍵字(從C99開始);不幸的是,到目前為止它還沒有被引入到C++中(因為在C++中引入它更復雜)。然而,許多編譯器確實有點支持它,例如__restrict
。
底線:編譯器在編譯f()
時必須支持您的深奧用例,并且不會有任何問題。
有關
restrict
的用例,請參閱this post。
這篇關于使用指向非常數的指針和指向相同地址的常量參數的指針的函數調用的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持IT屋!
查看全文