Loose-Info.com
Last Update 2024/01/10
TOP - 各種テスト - C言語 - ポインタ

テスト概要

ポインタの宣言・演算例
配列、ポインタ、ポインタのポインタによる各要素へのアクセス例
関数引数としてのポインタの使用に関する試行
引数にポインタを含む関数の値渡しとポインタ渡しの比較


ポインタの宣言・演算例


sample.c
#include <stdio.h> #include <stdlib.h> int main(void) { unsigned char uc[3] = {1, 2, 3}; int i[3] = {4, 5, 6}; double d[3] = {7.0, 8.0, 9.0}; unsigned char *puc = &uc[0]; /* unsigned char型ポインタの宣言・初期化 */ int *pi = &i[0]; /* int型ポインタの宣言・初期化 */ double *pd = &d[0]; /* double型ポインタの宣言・初期化 */ printf("unsigned int\n"); printf("uc[0](%p) = %d 初期値\n", puc, *puc); puc++; printf("uc[1](%p) = %d ポインタ加算\n", puc, *puc); puc++; printf("uc[2](%p) = %d ポインタ加算\n", puc, *puc); printf("\n"); printf("int\n"); printf("i[0](%p) = %d 初期値\n", pi, *pi); pi++; printf("i[1](%p) = %d ポインタ加算\n", pi, *pi); pi++; printf("i[2](%p) = %d ポインタ加算\n", pi, *pi); printf("\n"); printf("double\n"); printf("d[0](%p) = %e 初期値\n", pd, *pd); pd++; printf("d[1](%p) = %e ポインタ加算\n", pd, *pd); pd++; printf("d[2](%p) = %e ポインタ加算\n", pd, *pd); return EXIT_SUCCESS; }

実行結果
$ gcc -Wall sample.c $ ./a.out unsigned int uc[0](0x7ffdba345f95) = 1 初期値 uc[1](0x7ffdba345f96) = 2 ポインタ加算 uc[2](0x7ffdba345f97) = 3 ポインタ加算 int i[0](0x7ffdba345f88) = 4 初期値 i[1](0x7ffdba345f8c) = 5 ポインタ加算 i[2](0x7ffdba345f90) = 6 ポインタ加算 double d[0](0x7ffdba345f70) = 7.000000e+00 初期値 d[1](0x7ffdba345f78) = 8.000000e+00 ポインタ加算 d[2](0x7ffdba345f80) = 9.000000e+00 ポインタ加算

配列、ポインタ、ポインタのポインタによる各要素へのアクセス例


sample.c
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { /* 個々の引数要素へのポインタを宣言・初期化 */ char *p1 = argv[0]; /* 最初の引数要素で初期化 */ /* 引数配列へのポインタを宣言・初期化 */ char **p2 = argv; printf("\n配列を使用して最初の引数要素にアクセス\n"); printf("argv[0] = %s\n", argv[0]); printf("argv[0][0] argv[0][1] = %c %c\n", argv[0][0], argv[0][1]); printf("\n最初の引数要素へのポインタを使用してアクセス\n"); printf("p1 = %s\n", p1); printf("*p1 *(p1+1) = %c %c\n", *p1, *(p1+1)); printf("\n引数配列へのポインタを使用して最初の引数要素にアクセス\n"); printf("*p2 = %s\n", *p2); printf("**p2 *(*p2+1) = %c %c\n\n", **p2, *(*p2+1)); if (argc > 1) { printf("\n配列を使用して2番目の引数要素にアクセス\n"); printf("argv[1] = %s\n", argv[1]); printf("argv[1][0] argv[1][1] = %c %c\n", argv[1][0], argv[1][1]); printf("\n2番目の引数要素へのポインタを使用してアクセス\n"); p1 = argv[1]; printf("p1 = %s\n", p1); printf("*p1 *(p1+1) = %c %c\n", *p1, *(p1+1)); printf("\n引数配列へのポインタを使用して2番目の引数要素にアクセス\n"); ++p2; printf("*p2 = %s\n", *p2); printf("**p2 *(*p2+1) = %c %c\n", **p2, *(*p2+1)); } return EXIT_SUCCESS; }

実行結果
$ gcc -Wall sample.c $ ./a.out sample 配列を使用して最初の引数要素にアクセス argv[0] = ./a.out argv[0][0] argv[0][1] = . / 最初の引数要素へのポインタを使用してアクセス p1 = ./a.out *p1 *(p1+1) = . / 引数配列へのポインタを使用して最初の引数要素にアクセス *p2 = ./a.out **p2 *(*p2+1) = . / 配列を使用して2番目の引数要素にアクセス argv[1] = sample argv[1][0] argv[1][1] = s a 2番目の引数要素へのポインタを使用してアクセス p1 = sample *p1 *(p1+1) = s a 引数配列へのポインタを使用して2番目の引数要素にアクセス *p2 = sample **p2 *(*p2+1) = s a

関数引数としてのポインタの使用に関する試行


sample.c
#include <stdio.h> #include <stdlib.h> #include <string.h> /* ポインタのポインタとして引数を受け取り、ポインタpの指すポインタ(文字列)の各文字のアドレスを出力 */ void func(int n, char **p) { for (int i=0; i < strlen(*(p + n)) + 1; i++) { if (*(*(p + n) + i) != '\0') { /* ヌル文字以外は文字とアドレスを表示 */ printf("%c --- %p\n", *(*(p + n) + i), *(p + n) + i); } else { /* ヌル文字は「\0」とアドレスを表示 */ printf("%s --- %p\n", "\\0", *(p + n) + i); } } } int main(int argc, char *argv[]) { /* 引数ベクトルポインタのアドレス、引数文字列の先頭アドレス、格納値を表示 */ for (int i=0; i<argc; i++) { printf("%p --- %p --- %s\n", argv + i, *(argv + i), *(argv + i)); } printf("\n"); for (int i=0; i<argc; i++) { /* main関数のargv(char配列へのポインタ)を引数としてfunc関数を呼び出し */ func(i, argv); printf("*(argv+%d) = %s\n\n", i, *(argv+i)); } return EXIT_SUCCESS; }

実行結果
$ gcc -Wall sample.c $ ./a.out 1234567890 abcde aa bb cc 0x7fff8fcee0a8 --- 0x7fff8fcef4cb --- ./a.out 0x7fff8fcee0b0 --- 0x7fff8fcef4d3 --- 1234567890 0x7fff8fcee0b8 --- 0x7fff8fcef4de --- abcde 0x7fff8fcee0c0 --- 0x7fff8fcef4e4 --- aa 0x7fff8fcee0c8 --- 0x7fff8fcef4e7 --- bb 0x7fff8fcee0d0 --- 0x7fff8fcef4ea --- cc . --- 0x7fff8fcef4cb / --- 0x7fff8fcef4cc a --- 0x7fff8fcef4cd . --- 0x7fff8fcef4ce o --- 0x7fff8fcef4cf u --- 0x7fff8fcef4d0 t --- 0x7fff8fcef4d1 \0 --- 0x7fff8fcef4d2 *(argv+0) = ./a.out 1 --- 0x7fff8fcef4d3 2 --- 0x7fff8fcef4d4 3 --- 0x7fff8fcef4d5 4 --- 0x7fff8fcef4d6 5 --- 0x7fff8fcef4d7 6 --- 0x7fff8fcef4d8 7 --- 0x7fff8fcef4d9 8 --- 0x7fff8fcef4da 9 --- 0x7fff8fcef4db 0 --- 0x7fff8fcef4dc \0 --- 0x7fff8fcef4dd *(argv+1) = 1234567890 a --- 0x7fff8fcef4de b --- 0x7fff8fcef4df c --- 0x7fff8fcef4e0 d --- 0x7fff8fcef4e1 e --- 0x7fff8fcef4e2 \0 --- 0x7fff8fcef4e3 *(argv+2) = abcde a --- 0x7fff8fcef4e4 a --- 0x7fff8fcef4e5 \0 --- 0x7fff8fcef4e6 *(argv+3) = aa b --- 0x7fff8fcef4e7 b --- 0x7fff8fcef4e8 \0 --- 0x7fff8fcef4e9 *(argv+4) = bb c --- 0x7fff8fcef4ea c --- 0x7fff8fcef4eb \0 --- 0x7fff8fcef4ec *(argv+5) = cc

引数にポインタを含む関数の値渡しとポインタ渡しの比較


sample.c
#include <stdio.h> #include <stdlib.h> /* 実引数へのポインタを使用する関数 */ /* argc(int)へのポインタ : pargc */ /* argv(char**)へのポインタ : pargv */ void func1(int *pargc, char ***pargv) { int argc = *pargc; /* 引数個数 */ char **argv = *pargv; /* 引数配列(char型配列へのポインタ) */ printf("引数個数格納変数アドレス : pargc = %p\n", pargc); printf("引数個数 : argc = %d\n\n", argc); printf("引数配列ポインタアドレス : pargv = %p\n", pargv); printf("引数配列ポインタ格納値 : argv = %p\n", argv); for (int i=0; i<argc; i++) { printf("argv[%d] = %p\n", i, argv[i]); printf("argv[%d] = %s\n", i, argv[i]); } } /* 実引数の値で仮引数を初期化する関数 */ void func2(int argc, char **argv) { printf("引数個数格納変数アドレス : &argc = %p\n", &argc); printf("引数個数 : argc = %d\n\n", argc); printf("引数配列ポインタアドレス : &argv = %p\n", &argv); printf("引数配列ポインタ格納値 : argv = %p\n", argv); for (int i=0; i<argc; i++) { printf("argv[%d] = %p\n", i, argv[i]); printf("argv[%d] = %s\n", i, argv[i]); } } int main(int argc, char *argv[]) { printf("引数個数格納変数アドレス : &argc = %p\n", &argc); printf("引数個数 : argc = %d\n\n", argc); printf("引数配列ポインタアドレス : &argv = %p\n", &argv); printf("引数配列ポインタ格納値 : argv = %p\n", argv); for (int i=0; i<argc; i++) { printf("argv[%d] = %p\n", i, argv[i]); printf("argv[%d] = %s\n", i, argv[i]); } printf("\n---------- func1 ----------\n"); func1(&argc, &argv); printf("\n---------- func2 ----------\n"); func2(argc, argv); return EXIT_SUCCESS; }

実行結果
$ gcc -Wall sample.c $ ./a.out 123 45678 引数個数格納変数アドレス : &argc = 0x7ffdedc53f2c 引数個数 : argc = 3 引数配列ポインタアドレス : &argv = 0x7ffdedc53f20 引数配列ポインタ格納値 : argv = 0x7ffdedc54058 argv[0] = 0x7ffdedc554d9 argv[0] = ./a.out argv[1] = 0x7ffdedc554e1 argv[1] = 123 argv[2] = 0x7ffdedc554e5 argv[2] = 45678 ---------- func1 ---------- 引数個数格納変数アドレス : pargc = 0x7ffdedc53f2c 引数個数 : argc = 3 引数配列ポインタアドレス : pargv = 0x7ffdedc53f20 <--- ポインタのポインタ渡しとなり、アドレスは実引数と同じ 引数配列ポインタ格納値 : argv = 0x7ffdedc54058 argv[0] = 0x7ffdedc554d9 argv[0] = ./a.out argv[1] = 0x7ffdedc554e1 argv[1] = 123 argv[2] = 0x7ffdedc554e5 argv[2] = 45678 ---------- func2 ---------- 引数個数格納変数アドレス : &argc = 0x7ffdedc53efc 引数個数 : argc = 3 引数配列ポインタアドレス : &argv = 0x7ffdedc53ef0 <--- ポインタの値渡しとなり、アドレスは実引数と異なる 引数配列ポインタ格納値 : argv = 0x7ffdedc54058 argv[0] = 0x7ffdedc554d9 argv[0] = ./a.out argv[1] = 0x7ffdedc554e1 argv[1] = 123 argv[2] = 0x7ffdedc554e5 argv[2] = 45678

実行環境

GNU bash, version 5.1.16
GCC-12.2.0
GNU C Library 2.36
GNU Binutils 2.39


コード例・出力内容中の表記

・実行例中の太字表記部分は、コマンドなどの入力された文字列を示します。
・「」や「...」の着色省略表記は、 実際のソースコードや出力内容などを省略加工した部分を示します。