非constと同じアドレスのconstの引数へのポインタへのポインタを持つ関数呼び出し

ウィリー:

私は、関数を書きたいというの入力データとポインタを使用して、データの別のアレイ出力の配列。

私は結果が、両方の場合は何か思ったんだけど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\n", s);
    return 0;
}

上記の質問に加えて、私は削除した場合、これは明確に定義されているconst元のコードでは?

einpoklum:

それは行動が明確に定義されていることは事実ですが- ありませんコンパイラは意味で「constのための最適化は、」あなたが意味することができていることというのは本当。

つまり、コンパイラがされていない使用可能なパラメータがあるという理由だけであることを前提とconst T* ptrによって、メモリが指摘ptr別のポインタによって変更されることはありません。ポインタでも同じである必要はありません。constそのポインタを通じて変更を行うことはないあなたによって義務(=機能) -義務ではなく、保証されています。

実際にその保証を持つために、あなたがポインタをマークする必要がrestrictキーワード。したがって、あなたがこの2つの関数をコンパイルした場合:

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(C99以降)C唯一のキーワードです。残念ながら、それは(より複雑にC ++でそれを導入することが悪い理由で)これまでにC ++に導入されていません。多くのコンパイラは、前述したように、しかし、それをちょっと-サポートしています__restrict

ボトムライン:コンパイラはコンパイル時に「難解な」ユースケースをサポートしている必要がありf()、それに問題はありません。


参照この記事のためのユースケースについてをrestrict

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=369507&siteId=1