C言語 2重ポインタと関数に渡すときのまとめ

ポインタを関数で使用するときのまとめ。
10年ぶりにC言語を書いて忘れていたので、思い出したのをまとめてみる。
関数をまたぐをわけわからなくなってくる。嵌るポイントはここ。
2重ポインタ ダブルポインタ ポインタのポインタ

値渡し=内容が別のアドレスにコピーされる。呼び出し元とは別ものになる。

関数に値を渡すとき何もしないと値渡しになるから、ポインタを渡すとポインタに格納されているアドレス自身を値渡しすることになる。
なので、渡した関数の中でアドレスを変更すると、値渡しなので関数終了時にアドレスが入った箱が破棄されるので、呼び出し元には反映されない。
関数内でmallocなどでアドレスを変更する場合は2重ポインタで渡せば、2重ポインタのアドレス自身が破棄されても、その実体であるポインタは残るので内容は維持できる。
内容を触るぶんには、アドレスは変更されないので問題なし。ポインタを値渡しすればよし。

●まとめ
・ポインタを関数に渡すとき、
  mallocする場合、二重ポインタで渡す。
  内容のみを触る場合、ポインタをそのまま値渡しすればOK
・3重ポインタなどは要らない

●ソース

#include <stdio.h>

void funcA(unsigned char **);
void funcAA(unsigned char *);
void funcB(unsigned char *);
void funcBB(unsigned char *);
void funcC(unsigned char **);
void funcCC(unsigned char ***);
void funcD(unsigned char **);
void funcDD(unsigned char ***);
void funcE(unsigned char **);
void funcEE(unsigned char **);

int main(){
unsigned char *szA;
unsigned char *szB;
unsigned char *szC;
unsigned char *szD;
unsigned char *szE;

printf(“nポインタ渡し→malloc→値渡し→内容を編集n”);
funcA(&szA);
printf(“A:%sn”,szA);

printf(“n値渡し→malloc→値渡し→内容を編集n”);
funcB(szB);
printf(“B:%sn”,szB);

printf(“nポインタ渡し→malloc→ポインタ渡し→内容を編集n”);
funcC(&szC);
printf(“C:%sn”,szC);

printf(“nポインタ渡し→ポインタ渡し→malloc→内容を編集n”);
funcD(&szD);
printf(“D:%sn”,szD);

printf(“nポインタ渡し→値渡し→malloc→内容を編集n”);
funcE(&szE);
printf(“E:%sn”,szE);
}

void funcA(unsigned char **szDoublePointer){
*szDoublePointer = (unsigned char *)malloc(100);
memset(*szDoublePointer,’’,100);

funcAA(*szDoublePointer);
printf(“AA:%sn”,*szDoublePointer);
}

void funcAA(unsigned char *szPointer){
strcpy(szPointer,”set funcAA”);
}

void funcB(unsigned char *szPointer){
szPointer = (unsigned char *)malloc(100);
memset(szPointer,’’,100);

funcBB(szPointer);
printf(“BB:%sn”,szPointer);
}

void funcBB(unsigned char *szPointer){
strcpy(szPointer,”set funcBB”);
}

void funcC(unsigned char **szDoublePointer){
*szDoublePointer = (unsigned char *)malloc(100);
memset(*szDoublePointer,’’,100);

funcCC(&szDoublePointer);
printf(“CC:%sn”,*szDoublePointer);
}

void funcCC(unsigned char ***szTriplePointer){
strcpy(**szTriplePointer,”set funcCC”);
}

void funcD(unsigned char **szDoublePointer){
funcDD(&szDoublePointer);
printf(“DD:%sn”,*szDoublePointer);
}

void funcDD(unsigned char ***szTriplePointer){
**szTriplePointer = (unsigned char *)malloc(100);
memset(**szTriplePointer,’’,100);
strcpy(**szTriplePointer,”set funcDD”);
}

void funcE(unsigned char **szDoublePointer){
funcEE(szDoublePointer);
printf(“EE:%sn”,*szDoublePointer);
}

void funcEE(unsigned char **szDoublePointer){
/*この場合はダブルポインタの値渡しであるが *
*ダブルポインタ自身を変更してるのではなく、 *
*ダブルポインタの実体(ポインタ)を変更しているので *
*変更内容が呼び出し元に反映される */
*szDoublePointer = (unsigned char *)malloc(100);
memset(*szDoublePointer,’’,100);
strcpy(*szDoublePointer,”set funcEE”);
}

●実行結果

ポインタ渡し→malloc→値渡し→内容を編集
AA:set funcAA
A:set funcAA

値渡し→malloc→値渡し→内容を編集
BB:set funcBB
B:U 藐VS隹x ←ポインタを値渡ししたので、関数内で編集した内容が破棄された

ポインタ渡し→malloc→ポインタ渡し→内容を編集
CC:set funcCC
C:set funcCC

ポインタ渡し→ポインタ渡し→malloc→内容を編集
DD:set funcDD
D:set funcDD

ポインタ渡し→値渡し→malloc→内容を編集
EE:set funcEE
E:set funcEE

わからなければ以下の本を参考にしてもいいかも(キーワード検索なので的外れの場合もあります)
わからなければ以下の本を参考にしてもいいかも(機械検索なので的外れの場合もあります)

C言語 2重ポインタと関数に渡すときのまとめ” への1件のコメント

  1. ダブルポインタの使用方法が分からず、こちらを参考にテストしました。が、strcpy() の引数にunsigned char* ですとwarnningがふいて・・・・。何か、コンパイルオプションが必要ですか??

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です