ポインタ定数および定数ポインタ
- const char *p, char * const p, const char * const p の違いについて
1. const
constはconstantの略記です。変数の前にconstが付くと、その変数内のデータはアクセス可能であり、変更できないことを意味します。つまり、constは"read-only"を意味します。変数を変更しようとすると、コンパイルエラーになります。constは、コンパイラがコンパイル時にチェックを行うことで確保されます(つまり、const変数が変更できないのは、実行時エラーではなくコンパイルエラーとなります)。そのため、コンパイラを騙す方法を見つければ、実行時エラーにならずにconst定義された定数を変更することができるのです。
ルールです。
- constが近くにある人は、改造できない。
- 定数は定義された後では変更できないため、const を使って変数を定義する場合は初期化する必要があります。
#include <stdio.h>
int main(void)
{
int i = 10;
int j = 20;
const int *ptr = &i;
printf("ptr: %d\n", *ptr);
*ptr = 100; /* error: object pointed cannot be modified using the pointer ptr */
ptr = &j; /* valid */
printf("ptr: %d\n", *ptr);
return 0;
}
2.定点
ポインタを宣言するとき、キーワードconstは型の前でも後でも、また両方の位置で使うことができます。定義の形式は次の3つです。
-
定数へのポインタ
- const int *ptr;
- int const *ptr;
-
変数への定数ポインタ
- int *const ptr;
-
定数ポインタ
- const int *const ptr;
個々の意味は以下の通りです。
-
const int * pOne;
-
int * const pTwo;
-
const int *const pThree;
-
ptr が指す値もポインタ ptr も変更できない。
3つの文章を覚えるために記憶を深めましょう。
ポインタとconstの前に誰が先に読むか。
* はアドレス、const は内容を表します。
前にいる人は変更不可。例
int const *p1 = &b; //前面にconstがあり、定数ポインタとして定義されています。
int *const p2 = &c; // *先行、ポインタ定数として定義されます。ポインタ定数 は定数へのポインタです。その名の通り、定数へのポインタです。つまり、変数を指すことはできず、指すものは変更できず、ポインタによって指すものは変更できませんが、ポインタ自体は定数ではなく、別の定数を指すようにそれ自体の値を変更することができます。
ポインタ定数 は、ポインタそのものが定数であることを意味します。それが指すアドレスは不変ですが、そのアドレスの内容はポインターによって変更することができます。それが指すアドレスは、その寿命が尽きるまで生き続けます。注意点としては、ポインタ定数は定義と同時に初期値を割り当てる必要があることです。
ケース1:ポインタbが指すアドレスの内容は変更できないが、ポインタbは他のアドレスを指すことができる。
#Change the contents of the address pointed to by pointer b int main() { int a = 2; int const *b = &a; *b = 3; // report error: expression must be a modifiable lvalue printf("albert:%d\n",a); } ---------------------------------------------------------------------------- #Change the pointer b to int main() { int a = 2; int b = 3; int const *c = &a; printf("albert:%p\n", c); c = &b; printf("albert:%p\n",c); }
ケース2:ポインタが指すアドレスは再割り当てできないが、中身は変更できる場合。
int main() { int a = 2; int b = 3; int *const c = &a; printf("albert:%p\n", c); c = &b; //rare: expression must be a modifiable lvalue printf("albert:%p\n",c); } -------------------------------------------------------------------------- int main() { int a = 2; int b = 3; int *const c = &a; *c = 4; printf("albert:%d\n",*c); //4 }
3. C言語におけるポインタと配列の違い
これまで見てきたように、配列を宣言すると、配列のセルに対して連続したメモリブロックが確保され、(適切な型の)ポインタセルが作成されます。 このポインタセルには配列の名前が与えられます。配列のセルにメモリが割り当てられると 配列のセルにメモリが割り当てられると 開始アドレスは固定です。 つまり、それは 変更不可 したがって、ポインタ・セルの値を変更してはならない。このポインタを変更しないようにするために、C言語では配列名を変数として使ってはいけません。 変数として使ってはいけません。 左側 として使用することはできません。 L値 . その代わり、必要であれば、適切な型の別のポインタ変数を宣言し、L値として使用することができる。例
#include <stdio.h> int main() { int a[] = { 1,5,10,20 }; int b = *a++; //*a++ is the same as *(a++) printf("b = %d\n",b); }
上に示すように、コンパイルはエラーを報告します:配列名が定数ポインタであるため、a++を実行できないので、変更を行います。
参考
http://ee.hawaii.edu/~tep/EE160/Book/chap7/subsection2.1.3.2.html
https://www.geeksforgeeks.org/difference-const-char-p-char-const-p-const-char-const-p/
-
ポインタpを変更することはできませんが、ptrが指す値を変更することは可能です。
-
const int *const pThree;
-
ptrが指す値は変更できないが、ポインタ自体は変更できる。
-
int * const pTwo;
関連
-
_CRT_SECURE_NO_WARNINGS エラーメッセージ、解決方法
-
解決済み] g++ コンパイルエラー: ')'トークンの前に一次式があることが予想される
-
g++が内部・外部コマンドソリューションとして認識されない、MinGWを初めて使うときの落とし穴
-
Cエラー [エラー] 代入_Ashesの左オペランドにlvalueが必要です-プログラマーズ・シークレット
-
#137: 式は変更可能なlvalueでなければならない問題 // 文字列配列の代入問題
-
[C] Error [Error] 代入の左オペランドとして lvalue が必要です。
-
Solve Dev-c++ [エラー] 'for' ループの初期宣言は、C99 または C11 モードでのみ許可されます。
-
関数 'malloc' の暗黙の宣言に対する解決策
-
initializer element is not constant "というエラーが表示されるのですが?
-
C: 1を求める! + 2! + 3! + ... + n! (ループ)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
C 構造体定義エラー: '['トークンの前に一次式があることが予想される
-
[C] レポートエラー 代入の左オペランドとしてlvalueが必要
-
libc++abi.dylib: NSException タイプの捕捉されない例外で終了するエラー
-
赤線の位置は必ずしも間違っていない:式は変更可能なlvalueでなければならないエラーは、この文とは別の場所に存在する可能性があります。
-
警告:代入がキャストなしで整数からポインタを作成する場合の修正方法に関する警告
-
VSCodeでCプログラムを書くとエラーになる:ソースファイル "stdio.h" を開くことができない
-
未定義の `__isoc99_sscanf' への参照
-
C 言語のポインタ配列のポインタ型、ポインタに値を割り当てるために配列名を使用、コンパイル時の警告:互換性のないポインタ型からの初期化
-
C/C++の再定義
-
コンパイルエラー:可変長オブジェクトが初期化されていない可能性があります。