13 KiB
13 KiB
title | author | date | wordtwit_post_info | categories | |||
---|---|---|---|---|---|---|---|
『新版C言語プログラミングレッスン 入門編』第11章・ポインタ | kazu634 | 2008-05-02 |
|
|
難関に入ります。
「ポインタ」とは何か?
「ポインタとは、変数のアドレスをもつ変数である」
とりあえず研修でハードウェアについてたたき込まれているので、この説明でなんとなくわかる。要は主記憶上のアドレスを格納できる変数を「ポインタ」という…みたいです。
「ポインタ」の定義の仕方
こんな感じだよー。
int *p;
「ポインタ」への代入
「&」演算子を用いると変数のアドレスがわかります。例:
p = &x;
「ポインタ」の参照
printfではこんな感じになる。
printf("%p\n", p);
また、ポインタが指している他の変数の値も参照できる。例えば
int x; int *p; x = 123; p = &x; *p = 456;
とすると、xの値が456になる。
「ポインタ」のインクリメントとか
- 「p++」: ポインタpが「一つ次」の変数を指すようになる
- 「p–」: ポインタpが「一つ前」の変数を指すようになる
例
#include <stdio.h> void swap_int(int *xp, int *yp); int main(void); void swap_int(int *xp, int *yp) { int tmp; tmp = *xp; *xp = *yp; *yp = tmp; } int main(void) { int x, y; x = 4; y = 5; printf ("x = %d, y = %d\n", x, y); swap_int(&x, &y); printf ("x = %d, y = %d\n", x, y); }
ここで個人的に注意すべきなのは、void swap_intのところでの「*xp」などといった表記は、「変数がポインタである」ことを示す。それに対して、以降の「*xp」などは「xpに入っているアドレスが参照している変数」を指す。この違いが分からず、ちょっと混乱してしまった。
配列とポインタの関係
ポインタのインクリメントは、おそらく配列の内部で使うことを想定しているのだと思われる。
#include <stdio.h> int main(void); int main(void) { int x[3] = {1, 3, 9}; int *p_x; int i; p_x = &x[]; for (i = ;i < 3;i++) { *p_x = *p_x * *p_x; p_x++; } for (i = ;i < 3;i++) { printf ("x[%d]: %d\n", i, x[i]); } return(); }
これは
#include <stdio.h> int main(void); int main(void) { int x[3] = {1, 3, 9}; int i; for (i = ;i < 3;i++) { x[i] = x[i] * x[i]; } for (i = ;i < 3;i++) { printf ("x[%d]: %d\n", i, x[i]); } return(); }
と結局同じことをしていることになる*1。
構造体と「ポインタ」の関係
#include <stdio.h> #include <string.h> int main(void); struct student { int id; char name[20]; int japanese; int math; int eng; }; int main(void) { struct student yukari; struct student *p; yukari.id = 1; strcpy(&yukari.name[], "Yukari"); yukari.japanese = 80; yukari.math = 70; yukari.eng = 100; p = /* 構造体のポインタを用いた参照はこのように書く */ (*p).id = 2; printf ("Yukari's id: %d\n", (*p).id); /* もしくはこのように書く */ p->id = 3; printf ("Yukari's id: %d\n", p->id); return(); }
練習問題
一つ目の変数の阿智が二つ目より小さいときには値を交換し、そうでないときには何もしない関数をポインタを用いて作るよ。
#include <stdio.h> void swap_bigint(int *x, int *y); int main(void); void swap_bigint(int *x, int *y) { int tmp; if (*x < *y) { tmp = *x; *x = *y; *y = tmp; } } int main(void) { int x, y; x = 5; y = 3; printf ("Setting Value: x -> %d, y -> %d\n", x, y); swap_bigint(&x, &y); printf ("After the swap_value: x -> %d, y -> %d\n", x, y); return(); }
*1:でも、私には二つ書き方があることは分かっても、二つの違いは分からなかったりorz。たぶん、効率とかなんかが違うのだと思われる