Last Update 2024/01/10
テスト概要
ポインタの宣言・演算例
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
GCC-12.2.0
GNU C Library 2.36
GNU Binutils 2.39
コード例・出力内容中の表記
・実行例中の太字表記部分は、コマンドなどの入力された文字列を示します。
・「︙」や「...」の着色省略表記は、 実際のソースコードや出力内容などを省略加工した部分を示します。
・「︙」や「...」の着色省略表記は、 実際のソースコードや出力内容などを省略加工した部分を示します。