C言語ポインタ配列初期化をマスター:ヒントとベストプラクティス
ポインタは別の変数のアドレスを格納する変数です。ポインタ変数名は「*」記号で前置する必要があります。通常変数と同様に、「ポインタ配列」を宣言でき、配列の各要素が配列タイプのアドレスを保持します。
C言語でポインタ配列を初期化する方法
ポインタ変数は宣言時に既存変数のアドレスを割り当てることで初期化できます。以下はポインタ初期化の例です:
int x = 10; int *y = &x;
デフォルトでは、ポインタ変数を含むすべての変数は「autoストレージクラス」に属します。つまり、ポインタ変数は予測不能なガベージ、ランダムなメモリアドレスを格納し、未定義動作やセグメンテーションフォルトエラーなどの潜在的リスクを引き起こす可能性があります。したがって、宣言時に特定の値を格納しない場合はNULLで初期化すべきです。
int *ptr = NULL;
「ポインタ配列」は各要素にアドレスを格納します。配列の型は対象変数の型と一致する必要があります。
staticキーワードを使用したポインタ配列初期化
staticキーワードを使用して、ポインタ配列の各要素に「0」を格納して初期化することもできます。
例
#include <stdio.h>
int main(){
static int *ptr[5];
for (int i = 0; i < 5; i++){
printf("ptr[%d] = %d\n", i, ptr[i]);
}
return 0;
}
出力
コードを実行して出力を確認してください:
ptr[0]= 0 ptr[1]= 0 ptr[2]= 0 ptr[3]= 0 ptr[4]= 0
整数ポインタ配列の初期化
ここでは整数ポインタ配列を宣言し、3つの整数変数のアドレスを格納します。
例
#include <stdio.h>
int main(){
int a = 10, b = 20, c = 30;
int *ptr[3] = {&a, &b, &c};
for (int i = 0; i < 3; i++){
printf("ptr[%d]: address: %d value: %d\n", i, ptr[i], *ptr[i]);
}
return 0;
}
出力
コードを実行して出力を確認してください:
ptr[0]: address: 6422040 value: 10 ptr[1]: address: 6422036 value: 20 ptr[2]: address: 6422032 value: 30
直接アドレスによるポインタ配列初期化
通常配列の各要素のアドレスを、ポインタ配列の対応する要素に格納できます。
例
#include <stdio.h>
int main(){
int arr[] = {10, 20, 30};
int *ptr[3] = {&arr[0], &arr[1], &arr[2]};
for (int i = 0; i < 3; i++){
printf("ptr[%d]: address: %d value: %d\n", i, ptr[i], *ptr[i]);
}
return 0;
}
出力
コードを実行して出力を確認してください:
ptr[0]: address: 6422032 value: 10 ptr[1]: address: 6422036 value: 20 ptr[2]: address: 6422040 value: 30
ベースアドレスによる配列走査
配列のベースアドレス(この場合「&arr[0]」)を取得すると、データ型のサイズ分ポインタが増加することを知っているため、後続要素のアドレスを取得できます。
したがって、ベースアドレス(配列名は0番目要素のアドレスと同じ)だけで配列を走査できます。
例1
以下の例を見てみましょう:
#include <stdio.h>
int main(){
int arr[] = {10, 20, 30};
int *ptr = arr;
for (int i = 0; i < 3; i++){
printf("ptr[%d]: address: %d value: %d\n", i, ptr+i, *(ptr+i));
}
return 0;
}
出力
コードを実行して出力を確認してください:
ptr[0]: address: 6422020 value: 10 ptr[1]: address: 6422024 value: 20 ptr[2]: address: 6422028 value: 30
例2: ポインタ配列を使用した2次元配列走査
この例では2次元配列を持ちます。各行の0番目要素のアドレスがポインタ配列に格納されます。走査時、ポインタ配列の各要素に格納されたアドレス(対応する行の0番目要素を指す)がインクリメントされ、各行の値を取得します。
#include <stdio.h>
int main(){
// 2d array
int arr[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
};
int ROWS = 2, COLS = 4;
int i, j;
// pointer
int (*ptr)[4] = arr;
// ポインタptr経由で配列要素を表示
for (i = 0; i < ROWS; i++) {
for (j = 0; j < COLS; j++) {
printf("%d ", *(ptr[i]+j));
}
printf("\n");
}
return 0;
}
出力
このコードを実行すると、以下の出力が得られます:
1 2 3 4 5 6 7 8
例3
ここではポインタ配列は実際には不要です。この2次元配列の名前をベースポインタとして使用し、行と列方向にインクリメントして与えられた2次元配列の要素を取得できます:
#include <stdio.h>
int main(){
// 2d array
int arr[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
};
int ROWS = 2, COLS = 4;
int i, j;
// pointer
int *ptr = arr;
// ポインタptr経由で配列要素を表示
for (i = 0; i < ROWS; i++){
for (j = 0; j < COLS; j++){
printf("%d ", *(ptr + i * COLS + j));
}
printf("\n");
}
return 0;
}
出力
出力は前のコードと類似しています:
1 2 3 4 5 6 7 8
文字ポインタ配列(文字列)の初期化
Cプログラミングでは、文字列はcharデータ型の配列です。配列名が0番目要素のアドレスも表すため、文字列は以下のように宣言できます:
char arr[] = "Hello";
ポインタ表記を使用すると、文字列はcharポインタに以下のように割り当てられます:
char *arr = "Hello";
その後、複数の文字列を格納するcharポインタ配列を以下のように宣言できます:
char *arr[3] = {"string1", "string2", "string3", ... };
例
以下の例では、コンピュータ言語名を格納するためにcharポインタ配列を使用しています:
#include <stdio.h>
int main(){
char *langs [10] = {
"PYTHON", "JAVASCRIPT", "PHP", "NODE JS", "HTML",
"KOTLIN", "C++", "REACT JS", "RUST", "VBSCRIPT"
};
for(int i = 0; i < 10; i++)
printf("%s\n", langs[i]);
return 0;
}
出力
このコードを実行すると、以下の出力が得られます:
PYTHON JAVASCRIPT PHP NODE JS HTML KOTLIN C++ REACT JS RUST VBSCRIPT
このプログラムでは、「langs」は10個の文字列の配列へのポインタです。したがって、「langs[0]」がアドレス5000を指すなら、「langs + 1」は2番目の文字列へのポインタを格納するアドレス5004を指します。
したがって、以下のループバリエーションも文字列配列の表示に使用できます:
for (int i = 0; i < 10; i++){
printf("%s\n", *(langs + i));
}
動的ポインタ配列の初期化
malloc()関数を使用して、ポインタ配列を動的に宣言・初期化できます。
例
以下の例を見てみましょう:
#include <stdio.h>
int main(){
int *arr = (int *)malloc (sizeof (int) * 5);
for(int i = 0; i < 5; i++){
arr[i] = i;
}
for (int x = 0; x < 5; x++){
printf("%d %d\n", x, arr[x]);
}
return 0;
}
出力
このコードを実行すると、以下の出力が得られます:
0 0 1 1 2 2 3 3 4 4
ユーザー入力を求め、値をポインタ配列の要素に割り当てることもできます:
for(i = 0; i < 5; i++){
scanf("%d", &x);
arr[i] = x;
}
C言語
- C言語関数完全ガイド:ユーザー定義関数と標準ライブラリ関数の基礎
- C#プリプロセッサディレクティブ:条件付きコンパイルとコード制御
- C#基礎:基本構文とオブジェクト指向概念をマスター
- C++ do-while文:構文、実践例、ネストしたループ
- C言語の型キャストと変換をマスターする
- C言語入出力(I/O)マスター:scanf()とprintf()徹底解説
- C#ファイルI/O:Stream、FileStream、StreamReader/Writerによる読み書き
- C 言語のループ完全ガイド: for、while、do-while を実例でマスター
- C言語 演算子の優先順位と結合規則:完全ガイド
- C++のstd::listをマスターする:構文、関数、実践例
- while文 vs do-while文:実践例で明確に比較