構造体と配列とポインタ

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
MAY

構造体と配列とポインタ

#1

投稿記事 by MAY » 14年前

次のコードでコンパイルすると実行時にエラーになるのですが、原因がわかりません。
それと、何か突っ込みどころがあったらどんどん突っ込んでください。
コンパイラはbccです。

コード:

#include <stdio.h>
#include <stdlib.h>

typedef struct{
	int n;
} Test;

void func(Test ***a)
{
	Test b;
	
	scanf("%d", &b.n);
	
	*a = (Test **)realloc(*a, sizeof(Test *) * (5 + 1));
	*a[5] = &b;
	printf("\n%d\n", (*a[5])->n);
}

int main(void)
{
	int i;
	Test **a;
	
	a = (Test **)malloc(sizeof(Test *) * 5);
	
	for(i = 0; i < 5; ++i){
		a[i] = (Test *)malloc(sizeof(Test));
		a[i]->n = i * 2;
	}
	
	for(i = 0; i < 5; ++i){
		printf("%d\n", a[i]->n);
	}
	
	func(&a);
	
	for(i = 0; i < 6; ++i){
		printf("%d\n", a[i]->n);
	}
	
	return 0;
}

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: 構造体と配列とポインタ

#2

投稿記事 by h2so5 » 14年前

10行目の変数 b の寿命を確認してみてください。

MAY

Re: 構造体と配列とポインタ

#3

投稿記事 by MAY » 14年前

bをグローバル変数にしてみても結果は同じでした……。

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: 構造体と配列とポインタ

#4

投稿記事 by h2so5 » 14年前

15,16行目の *a[5] ですが、演算子の優先順位の関係で正しい配列へのアクセスになっていません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 構造体と配列とポインタ

#5

投稿記事 by softya(ソフト屋) » 14年前

この場合Test b;はグローバル変数でもローカル変数でもなくmallocすべきだと思いますが。
他のポインタと一貫性がありませんのでfreeで解放する時にエラーになる可能性が高くなります。
ちなみにローカル変数は絶対に、こういう場合に使ってはいけません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

MAY

Re: 構造体と配列とポインタ

#6

投稿記事 by MAY » 14年前

次のようにするとうまくいきました。ありがとうございました!

コード:

void func(Test ***a)
{
	Test *b = (Test *)malloc(sizeof(Test));
	
	scanf("%d", &b->n);
	
	*a = (Test **)realloc(*a, sizeof(Test *) * (5 + 1));
	(*a)[5] = b;
}

MAY

Re: 構造体と配列とポインタ

#7

投稿記事 by MAY » 14年前

それとすみません、次のコードについてなんですが、この場合、
変数eがローカル変数でも正常に動作するようなのですが、
理由を教えてくれたら幸いです。

コード:

#include <stdio.h>

void f(int **d)
{
	int e;
	
	scanf("%d", &e);
	
	*d = &e;
}

int main(void)
{
	int *b, c = 777;
	
	b = &c;
	printf("%d\n", *b);
	
	f(&b);
	printf("%d\n", *b);
	
	return 0;
}

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: 構造体と配列とポインタ

#8

投稿記事 by h2so5 » 14年前

19行目の関数を抜けたときにローカル変数eの寿命は終わっていますが、
20行目のprintfの引数に渡した時点では、まだスタック領域が上書きされずにデータが残っていたためたまたま上手く動作したに過ぎません。

MAY

Re: 構造体と配列とポインタ

#9

投稿記事 by MAY » 14年前

何度もありがとうございます!

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 構造体と配列とポインタ

#10

投稿記事 by softya(ソフト屋) » 14年前

お使いのコンパイラの実装に依存します。
ローカル変数がスタック上の取られている実装の場合は値が破壊されるまで参照可能な場合が多いですが単なる偶然です。

例えばこうすると値が壊れるはずです。

コード:

#include <stdio.h>
 
void f(int **d)
{
    int e;
    
    scanf("%d", &e);
    
    *d = &e;
}
 
int main(void)
{
    int *b, c = 777;
    
    b = &c;
    printf("(1) %d\n", *b);
    
    f(&b);
    printf("(2) %d\n", *b);
    printf("(3) %d\n", *b);
    
    return 0;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

“C言語何でも質問掲示板” へ戻る