使用指向非常數的指針和指向相同地址的常量參數的指針的函數調用 [英] Function call with pointer to non-const and pointer to const arguments of same address

查看:0
本文介紹了使用指向非常數的指針和指向相同地址的常量參數的指針的函數調用的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我要編寫一個函數,該函數使用指針輸入一個數據數組并輸出另一個數據數組。

我想知道,如果srcdst都指向同一個地址,結果會是什么,因為我知道編譯器可以針對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屋!

查看全文
登錄 關閉
掃碼關注1秒登錄
發送“驗證碼”獲取 | 15天全站免登陸
全免费A级毛片免费看无码播放