C言語について学習し始めて、ポインタ周りで苦戦している。
今回は、int型変数とint型の配列変数を作成してみて、それぞれいろいろな表記を行ってみて何を指し示しているのかを整理してみた。
変数定義
このようにint型変数・int型の配列変数と、それぞれのポインタ変数を定義。
▼変数定義
int val = 100 int *p_val = &val; int numbers[5] = {10, 20, 30, 40, 50}; int *p_numbers = numbers;
いろいろな出力値
いろいろな出力値をまとめた。
(出力例のポインタ値は実行環境によって変わる。)
▼変数valについての出力いろいろ
表記例 | 表記方法 | 出力例 | 解説 |
---|---|---|---|
val | 変数名のみ | 100 | 通常値 |
&val | 変数名にアドレス演算子 | 0x16b1ff5f8 | ポインタ値 |
(*val) | 変数名に間接参照演算子 | エラー | (間接参照演算子はポインタ変数にしか使えない) |
ポインタ変数p_valについての出力いろいろ
表記例 | 表記方法 | 出力例 | 解説 |
---|---|---|---|
p_val | 変数名のみ | 0x16b1ff5f8 | ポインタ値 |
&p_val | 変数名にアドレス演算子 | 0x16d11b5f0 | ポインタのポインタ値 |
*p_val | 変数名に間接参照演算子 | 100 | 元の値 |
配列変数numbersについての出力いろいろ
表記例 | 表記方法 | 出力例 | 解説 |
---|---|---|---|
numbers | 配列変数名のみ | 0x16b1ff600 | ポインタ値 |
&numbers | 配列変数名にアドレス演算子 | 0x16ee8b600 | 先頭要素のポインタ値 |
*numbers | 配列変数名に間接参照演算子 | 10 | 先頭要素の値 |
numbers[0] | 配列変数名に添字0 | 10 | 先頭要素の値 |
numbers[3] | 配列変数名に添字i | 40 | i番目の要素の値 |
&numbers[0] | 配列変数名に添字0とアドレス演算子 | 0x16bc2f600 | 先頭要素のポインタ値 |
&numbers[3] | 配列変数名に添字iとアドレス演算子 | 0x16bc2f60c | i番目の要素のポインタ値 |
*numbers[0] | 配列変数名に添字0と間接参照演算子 | 10 | 先頭要素の値 |
*numbers[3] | 配列変数名に添字iと間接参照演算子 | 40 | i番目の要素の値 |
ポインタ変数p_numbersについての出力いろいろ
表記例 | 表記方法 | 出力例 | 解説 |
---|---|---|---|
p_numbers | ポインタ変数名のみ | 0x16b1ff600 | ポインタ値 |
&p_numbers | ポインタ変数名にアドレス演算子 | 0x16bc2f60c | 先頭要素のポインタのポインタ値 |
*p_numbers | ポインタ変数名に間接参照演算子 | 10 | 先頭要素の値 |
p_numbers[0] | ポインタ変数名に添字0 | 10 | 先頭要素の値 |
p_numbers[3] | ポインタ変数名に添字i | 40 | i番目の要素の値 |
&p_numbers[0] | ポインタ変数名に添字0とアドレス演算子 | 0x16bc2f600 | 先頭要素のポインタ値 |
&p_numbers[3] | ポインタ変数名に添字iとアドレス演算子 | 0x16bc2f60c | i番目の要素のポインタ値 |
*p_numbers[0] | ポインタ変数名に添字0と間接参照演算子 | 10 | 先頭要素の値 |
*p_numbers[3] | ポインタ変数名に添字iと間接参照演算子 | 40 | i番目の要素の値 |
サンプルコード
▼いろいろな出力を実験
#include <stdio.h> int main() { /* 変数の定義と初期化 */ int val = 100; int numbers[5] = {10, 20, 30, 40, 50}; /* ポインタ変数の定義と初期化:変数名の先頭に*をつけるとポインタ型を示す(ポインタ定義の*) */ int *p_val = &val; // 変数名の先頭に&を使うと、その変数のポインタ値を示す(アドレス演算子&) int *p_numbers = numbers; // 配列変数の時は、添字なしの変数名がその変数の先頭のポインタ値を示す /* 値渡しと参照渡し */ // 値渡し:通常の関数定義のとき int myfunction01(int val); // 参照渡し:関数の仮引数にポインタ型を指定したいときはこのポインタ定義の*を使って渡す int myfunction02(int *val, int *numbers); /* 変数valについての出力いろいろ */ printf("変数名のみ(通常値) val = %d\n", val); // 100 printf("変数名にアドレス演算子(ポインタ値) &val = %p\n", &val); // 0x16b1ff5f8 // printf("変数名に間接参照演算子() *val = %d\n", *val); // エラー /* ポインタ変数p_valについての出力いろいろ */ printf("ポインタ変数名のみ(ポインタ値) p_val = %p\n", p_val); // 0x16b1ff5f8 printf("ポインタ変数名にアドレス演算子(ポインタのポインタ値) &p_val = %p\n", &p_val); // 0x16d11b5f0 printf("ポインタ変数名に間接参照演算子(元の値) *p_val = %d\n", *p_val); // 100 /* 配列変数numbersについての出力いろいろ */ printf("配列変数名のみ(先頭要素のポインタ値) numbers = %p\n", numbers); // 0x16b1ff600 printf("配列変数名にアドレス演算子(先頭要素のポインタ値) &numbers = %p\n", &numbers); // 0x16ee8b600 printf("配列変数名に間接参照演算子(先頭要素の値) *numbers = %d\n", *numbers); // 10 printf("配列変数名に添字0(先頭要素の値) numbers[0] = %d\n", numbers[0]); // 10 printf("配列変数名に添字i(要素の値) numbers[3] = %d\n", numbers[3]); // 40 printf("配列変数名に添字0とアドレス演算子(先頭要素のポインタ値) &numbers[0] = %p\n", &numbers[0]); // 0x16bc2f600 printf("配列変数名に添字iとアドレス演算子(i番目の要素のポインタ値) &numbers[3] = %p\n", &numbers[3]); // 0x16bc2f60c printf("配列変数名に添字0と間接参照演算子(先頭要素の値) *numbers[0] = %d\n", p_numbers[0]); // 10 printf("配列変数名に添字iと間接参照演算子(i番目の要素の値) *numbers[3] = %d\n", p_numbers[3]); // 40 /* ポインタ変数p_numbersについての出力いろいろ */ printf("ポインタ変数名のみ(ポインタ値) p_numbers = %p\n", p_numbers); // 0x16b1ff600 printf("ポインタ変数名にアドレス演算子(先頭要素のポインタのポインタ値) &p_numbers = %p\n", &p_numbers); // 0x16ee8b600 printf("ポインタ変数名に間接参照演算子(先頭要素の値) *p_numbers = %d\n", *p_numbers); // 10 printf("ポインタ変数名に添字0(先頭要素の値) numbers[0] = %d\n", p_numbers[0]); // 10 printf("ポインタ変数名に添字i(要素の値) numbers[3] = %d\n", p_numbers[3]); // 40 printf("ポインタ変数名に添字0とアドレス演算子(先頭要素のポインタのポインタ値) &p_numbers[0] = %p\n", &numbers[0]); // 0x16ee8b600 printf("ポインタ変数名に添字iとアドレス演算子(i番目の要素のポインタのポインタ値) &p_numbers[3] = %p\n", &numbers[3]); // 0x16ee8b60c printf("ポインタ変数名に添字0と間接参照演算子(先頭要素の値) *p_numbers[0] = %d\n", p_numbers[0]); // 10 printf("ポインタ変数名に添字iと間接参照演算子(i番目の要素の値) *p_numbers[3] = %d\n", p_numbers[3]); // 40 return 0; }