16

私はconstCコードでどのように使用すべきかを理解しようとしています。最初はあまり気にしませんでしたが、const全体でかなりの数の使用例を見ました。私は努力して戻って、宗教的に適切な変数を作成する必要がありますconstか?それとも私は自分の時間を無駄にしているだけですか?

特に関数呼び出しで、人間とコンパイラの両方で、変更が予想される変数を読みやすくなると思います。他に重要な点がありませんか?

4

4 に答える 4

13

const入力されますが、#defineマクロは入力されません。

constCブロックによってスコープが設定#defineされ、ファイル(またはより厳密にはコンパイル単位)に適用されます。

constパラメータの受け渡しで最も役立ちます。ポインタをconst使用したプロトタイプで使用されている場合は、関数が変更しないため、配列または構造体を渡しても安全であることがわかります。いいえconst、できます。

などの定義をstrcpy()見ると、私が何を意味するかがわかります。最初に関数プロトタイプに「const-ness」を適用します。レトロフィットconstは「多くの作業」ほど難しくはありません(ただし、時間単位で支払いを受ければ問題ありません)。

また、考慮してください:

const char *s = "Hello World";
char *s = "Hello World";

どちらが正しいのか、そしてその理由は?

于 2013-01-18T15:17:58.503 に答える
7

Cでconstキーワードを最もよく使用するにはどうすればよいですか?

「読み取り専用」constにしたい場合に使用します。とても簡単です:)

于 2013-01-18T15:17:27.847 に答える
3

使用constすることは良い習慣であるだけでなく、コードの読みやすさと理解しやすさを改善し、いくつかの一般的なエラーを防ぐのに役立ちます。必要に応じて、必ずconstを使用してください。

于 2013-01-18T15:16:34.447 に答える
1

定数を変更しようとしたときにコンパイラエラーが発生し、定数を非定数パラメータとして渡すことでコンパイラガードとして機能するほか、コンパイラは値が変更されないことを認識して特定の最適化を実行できるため、次のことが可能になります。値は変更されないため、値をキャッシュし、メモリから新しく読み取る必要はありません。また、値をコードですぐに置き換えることができます。

C const

const基本的にregisterは反対でvolatileあり、使用volatileすると、ファイルとブロックスコープでのconst最適化、およびブロックスコープでの最適化がオーバーライドされますregister。constはgccC-O0のブロックスコープでCに対して何も行わず、-O1以降では冗長であるため、同じ出力を生成します。したがって、最適化のみがconst register-O0で適用され、-O1以降では冗長になります。registerregister

#include<stdio.h>

int main() {
    const int i = 1;
    printf("%d", i);
}
.LC0:
  .string "%d"
main:
  push rbp
  mov rbp, rsp
  sub rsp, 16
  mov DWORD PTR [rbp-4], 1
  mov eax, DWORD PTR [rbp-4] //load from stack isn't eliminated for block-scope consts on gcc C unlike on gcc C++ and clang C, even though value will be the same
  mov esi, eax
  mov edi, OFFSET FLAT:.LC0
  mov eax, 0
  call printf
  mov eax, 0
  leave
  ret

この例では、-O0 、、を使用すると、constすべて同じコードが生成されますが、cfが異なるだけです。volatileautoregister

#include<stdio.h>
const int i = 1;
int main() {
    printf("%d", i);
}
i:
  .long 1
.LC0:
  .string "%d"
main:
  push rbp
  mov rbp, rsp
  mov eax, DWORD PTR i[rip] //load from memory
  mov esi, eax
  mov edi, OFFSET FLAT:.LC0
  mov eax, 0
  call printf
  mov eax, 0
  pop rbp
  ret

const int i = 1;代わりに:

i:
  .long 1
.LC0:
  .string "%d"
main:
  push rbp
  mov rbp, rsp
  mov eax, 1  //saves load from memory, now immediate
  mov esi, eax
  mov edi, OFFSET FLAT:.LC0
  mov eax, 0
  call printf
  mov eax, 0
  pop rbp
  ret

C ++ const

#include <iostream>

int main() {
    int i = 1;
    std::cout << i;
}
main:
  push rbp
  mov rbp, rsp
  sub rsp, 16
  mov DWORD PTR [rbp-4], 1 //stores on stack
  mov eax, DWORD PTR [rbp-4] //loads the value stored on the stack
  mov esi, eax
  mov edi, OFFSET FLAT:_ZSt4cout
  call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
  mov eax, 0
  leave
  ret

#include <iostream>

int main() {
    const int i = 1;
    std::cout << i;
}
main:
  push rbp
  mov rbp, rsp
  sub rsp, 16
  mov DWORD PTR [rbp-4], 1 //stores it on the stack
  mov esi, 1               //but saves a load from memory here, unlike on C
                           //'register' would skip this store on the stack altogether
  mov edi, OFFSET FLAT:_ZSt4cout
  call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
  mov eax, 0
  leave
  ret

#include <iostream>
int i = 1;
int main() {

    std::cout << i;
    }
i:
  .long 1
main:
  push rbp
  mov rbp, rsp
  mov eax, DWORD PTR i[rip] //load from memory
  mov esi, eax
  mov edi, OFFSET FLAT:_ZSt4cout
  call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
  mov eax, 0
  pop rbp
  ret

#include <iostream>
const int i = 1;
int main() {

    std::cout << i;
    }
main:
  push rbp
  mov rbp, rsp
  mov esi, 1 //eliminated load from memory, now immediate
  mov edi, OFFSET FLAT:_ZSt4cout
  call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
  mov eax, 0
  pop rbp
  ret

C ++には、aconstが初期化されていない場合(ファイルスコープとブロックスコープの両方)にコンパイラエラーを生成するという追加の制限があります。constまた、C++のデフォルトとして内部リンケージがあります。volatileそれでもオーバーライドconstしますregisterconst register、C++で両方の最適化を組み合わせます。

上記のすべてのコードはデフォルトの暗黙的な-O0を使用してコンパイルされますが、-Ofastを使用してコンパイルすると、const驚くべきことに、ファイルスコープのclangまたはgccのCまたはC++では冗長ではありませんconstsconstファイルスコープ変数がコードで変更されていない場合でも、使用されない限り、メモリからのロードは最適化されません。https://godbolt.org/z/PhDdxk

于 2020-04-10T16:38:31.183 に答える