• ベストアンサー

ポインタの指しているアドレスは同じなのに表示される内容が違う。

行列に関するプログラムです。 ライブラリのヘッダファイル matrix.h #ifndef MATRIX_H #define MATRIX_H #ifdef __cplusplus extern "C"{ #endif typedef struct{ int row,col; double *elements; } MATRIX; extern int matrix_error_code; extern MATRIX zero_matrix(MATRIX a); extern MATRIX identity_matrix(MATRIX a); extern void func_matrix(MATRIX a); #ifdef __cplusplus } #endif #endif ライブラリのソースファイル matrix.c #include <stdio.h> #include <stdlib.h> #include <math.h> #include "matrix.h" int matrix_error_code = 0; MATRIX zero_matrix(MATRIX a) /*零行列をつくる*/ { int i,size; double *p; size=a.row*a.col; for(i=0;i<size;i++) { if((p = malloc(sizeof(double))) == NULL) { puts("メモリを確保できません."); exit(0); } *p=0; } a.elements=p-size; return a; } MATRIX identity_matrix(MATRIX a) /*単位行列をつくる*/ { int i; a=zero_matrix(a); for(i=0;i<a.row;i++) { *(a.elements+i*a.col+i)=1.0000; } return a; } void func_matrix(MATRIX a) { int i,j; double *p; printf("b.elementsの値:%p\n",a.elements); printf("b[1,1]の値:%lf\n",a.elements); } 動作確認用のアプリケーションファイル test_matrix.c #include <stdio.h> #include "matrix.h" int main(void) { int i,j; MATRIX b; b.row=2; b.col=2; b=identity_matrix(b); for(i=0;i<b.row;i++) { for(j=0;j<b.col;j++) { printf("%3.4lf ",*(b.elements+i*b.col+j)); } printf("\n"); } printf("\n\n"); printf("b.elementsの値:%p\n",b.elements); printf("b[1,1]の値:%lf\n",b.elements); func_matrix(b); return 0; } void func_matrix(MATRIX a)内のprintf("b.elementsの値:%p\n",a.elements);とtest_matrix.c内のprintf("b.elementsの値:%p\n",b.elements);で表示される値は同じなので、main関数のbがvoid func_matrix(MATRIX a)内のaに正しく引き渡されていると思うのですが、それぞれの次の行での、printf("b[1,1]の値:%lf\n",b.elements);とprintf("b[1,1]の値:%lf\n",a.elements);とでは表示される値が違い、理由がわからず困っています。 どうか回答をよろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • trapezium
  • ベストアンサー率62% (276/442)
回答No.4

>for(i=0;i<size;i++) >{ >if((p = malloc(sizeof(double))) == NULL) >{ >puts("メモリを確保できません."); >exit(0); >} >*p=0; >} これではメモリリークしてます。 a.elements = p = malloc(sizeof(double) * size); if (NULL == p) exit(1); for (i = 0; i < size; i++) *p++ = 0.0; などとします。 それについでに言えば、 MATRIX hoge_matrix(MATRIX a) などは無駄なので、 void hoge_matrix(MATRIX *a) でいいと思う。呼び出し側はhoge_matrix(&b)

shuta1976
質問者

お礼

回答ありがとうございました。とても参考になりました。 メモリをまとめて確保することにはこれからしっかり気をつけて いきたいと思います。 本当にありがとうございました。

その他の回答 (3)

  • prophetok
  • ベストアンサー率44% (13/29)
回答No.3

#1&#2ですが MATRIX zero_matrix(MATRIX a) /*零行列をつくる*/ をみてみると、そもそもポインタが全く理解できていませんね。 質問以前にもう少し勉強しましょう。

  • prophetok
  • ベストアンサー率44% (13/29)
回答No.2

#1は間違い やりたいことは printf("b[1,1]の値:%lf\n",a.elements); ↓ printf("b[1,1]の値:%lf\n",*a.elements); だよね

  • prophetok
  • ベストアンサー率44% (13/29)
回答No.1

ざっとみただけですか。 配列の添え字は0から始まるという基本中の基本を忘れていませんか?

shuta1976
質問者

補足

ここで言う配列とは、プログラムではなく数学的な添え字としていました。誤解を与えてしまったようです。

関連するQ&A

  • エラーの原因が分かりません "undefined reference to"

    ライブラリのヘッダファイル matrix.h #ifndef MATRIX_H #define MATRIX_H #ifdef __cplusplus extern "C"{ #endif typedef struct{ int row,col; double *elements; } MATRIX; extern int matrix_error_code; extern void zero_matrix(MATRIX *a); extern void identity_matrix(MATRIX *a); extern void show_matrix(MATRIX *x); extern MATRIX multiply_matrix(MATRIX *a,MATRIX *b); extern MATRIX transposed_matrix(MATRIX *a); #ifdef __cplusplus } #endif #endif ライブラリのソースファイル matrix.c #include <stdio.h> #include <stdlib.h> #include <math.h> #include "matrix.h" int matrix_error_code = 0; void zero_matrix(MATRIX *a) { int i,size; double *p; size=a->row*a->col; if((p = malloc(sizeof(double)*size)) == NULL) { puts("メモリを確保できません."); exit(0); } a->elements=p; for(i=0;i<size;i++) *p++=0; } void identity_matrix(MATRIX *a) { int i; zero_matrix(a); for(i=0;i<a->row;i++) { *(a->elements+i*a->col+i)=1.0000; } } void show_matrix(MATRIX *x) { int i,j; for(i=0;i<x->row;i++) { for(j=0;j<x->col;j++) { printf("%3.4lf ",*(x->elements+i*x->col+j)); } printf("\n"); } printf("\n"); } MATRIX transposed_matrix(MATRIX *a) { MATRIX x; int i,j; double *p; if((p = malloc(sizeof(double)*(a->row*a->col))) == NULL) { puts("メモリを確保できません."); exit(0); } x.elements=p; x.row=a->col; x.col=a->row; for(i=0;i<x.row;i++) { for(j=0;j<x.col;j++) { *p++=*(a->elements+j*x.row+i); } } return x; } MATRIX multiply_matrix(MATRIX *a,MATRIX *b) { int i,j,k; double *p; MATRIX x; x.row=a->row; x.col=b->col; if((p = malloc(sizeof(double)*(x.row*x.col))) == NULL) { puts("メモリを確保できません."); exit(0); } x.elements=p; for(i=0;i<x.row;i++) { for(j=0;j<x.col;j++) { for(k=0;k<a->col;k++) { *p += *(a->elements+i*a->col+k) * *(b->elements+k*b->row+j); } } p++; } return x; } 動作確認のアプリケーションファイル test_matrix.c #include <stdio.h> #include "matrix.h" int main(void) { int i,j; MATRIX b,c,d,f; b.row=c.row=2; b.col=c.col=2; identity_matrix(&b); identity_matrix(&c); d=transposed_matrix(&b); show_matrix(&d); f=multiply_matrix(&b,&c); show_matrix(&f); return 0; } ライブラリのコンパイルまではエラーなしで出来るのですが、test_matrix.cをコンパイルすると、"undefined reference to '_transposed_matrix'"と、"undefined reference to '_multiply_matrix'"の2つが表示されてコンパイルができません。 どうかよろしくお願いします。

  • gcc: incompatible pointer type

    以下のCソースでコンパイルすると、warning: passing arg 1 of `func_b' from incompatible pointer type となります。 void (*p_func)() は、引数を省略しているので int として扱われるということでしょうか? #include <stdio.h> #include <stdlib.h> void func_a( unsigned char x ){ printf( "x=%d\n", x ) ; } void func_b( void (*p_func)() ){ p_func( 1 ) ; } int main(){ func_b( func_a ) ; return 0 ; }

  • C言語の初歩的な質問

    質問1----------------------------------------- #include<stdio.h> int main() {  int a;  char b[10];  for(int i = 0;i < 2;i++){   scanf("%d",&a);   printf("整数%d\n",a);  }  scanf("%s",b);  printf("文字列%s\n",b); } /* この際に、例えばabと入力すると結果が 整数-858993460 整数-858993460 文字列ab となり整数入力を無視して進められるのはなぜでしょうか? */ 質問2----------------------------------------- #include<stdio.h> void func(int**); int main() {  int *p;  func(&p);  printf("%d",*p); } void func(int **pp) {  int n = 10;  *pp = &n; } /* func関数のnはスコープからはずれて変数の寿命がなくなるはずなのにprintfで表示されるのはなぜでしょうか? */ ---------------------------------------------- C言語は一冊の本とネットの入門サイトをかじった程度の理解です。

  • ポインタについて

    下記プログラムはどういう動きをしているのでしょうか。 「printf("&a\t--> %p\n", &a );」は、なぜ「&a」なのでしょうか。 aはポインタ変数として宣言してあるのだから、アドレスを表す場合、「a」ではないのでしょうか。 「a = &value;」でvalueのアドレスをaに受け渡していると思うのですが、この場合、1つのアドレスを複数の変数が指しているということでしょうか。 aの値を25に書き換えれば、valueの値も25になるのでしょうか。 では逆にvalueの値を30に書き換えれば、aの値も30になるのでしょうか。 #include <stdio.h> int main() { int value = 10; int *a; printf("&value\t--> %p\n", &value); printf("&a\t--> %p\n", &a ); a = &value; printf("*a\t--> %d\n", *a ); *a = 25; printf("value \t--> %d\n", value ); return 0; }

  • 引数で指定された配列の要素数の取得

    どうもこんにちは。 C言語でプログラムを作成しています。 ある関数に配列を渡すことを考えていますが、渡した配列の要素数を取得する方法は何かありますか? 標準の関数を見ても、配列の先頭アドレスのポインタとともに、配列の要素数を渡しているものばかりで、配列のポインタを渡しているものは見かけません。 要素数があらかじめわかっていれば、それを引数の型に指定できますが、呼び出されるまで不明な場合はうまくいきません。 配列の要素数も引数として一緒に渡す必要がありますか? [作ってみたサンプル] #include <stdio.h> #include <stdlib.h> #include <string.h> // func1 と func2 をまとめられないだろうか。。。 void func1(int (*p)[10]) { ________int n = sizeof(*p) / sizeof((*p)[0]); ________int i; ________for (i = 0; i < n; i++) { ________________printf("%d\n", (*p)[i]); ________} ________printf("\n"); } void func2(int (*p)[5]) { ________int n = sizeof(*p) / sizeof((*p)[0]); ________int i; ________for (i = 0; i < n; i++) { ________________printf("%d\n", (*p)[i]); ________} ________printf("\n"); } int main(int argc, char *argv[]) { ________int ary1[10] = { 2, 4, 6, 8, 0, 1, 3, 5, 7, 9 }; ________int ary2[5] = { 3, 6, 9, 12, 15 }; ________func1(&ary1); ________func2(&ary2); ________return 0; }

  • ポインタのポインタ

    #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char **argv){ int i; if(argc != 2) { fprintf(stderr, "Usage: %s vector\n\tEx: %s 11110000\n", argv[0], argv[0]); return 1; } for(i=0;i<8;i++){ if(**argv == '0'){ printf("%d\n",i); } else{ printf("A%d\n",i); } argv++; } return 0; } コンパイルして./a.exe 10010011などと入力しても A0 A1 Segmentation Faultとなります。 どうすれば、 A1 0 ・・・省略 for文で回した8回分、出力が可能になるのか教えてください。 初歩的な質問ですいません。

  • ポインタのエラー?

    配列とポインタを使って多数桁の加算をするプログラムを作ったのですが、演算結果を表示した後にエラーが出てしまいます。初心者なので書式もばらばらで読みにくいと思いますが、お願いします。 #include <stdio.h> #include <stdlib.h> #define N 10 void main() { int *a,*b,*result,carry,i; a=(int *)calloc(N+1,sizeof(int)); b=(int *)calloc(N+1,sizeof(int)); result=(int *)calloc(N+1,sizeof(int)); /*配列aへの読み込み*/ for(i=1;i<N+1;i++) scanf("%d",&*(a+i)); *a=0; printf("入力された数値:"); for(i=1;i<N+1;i++) printf("%d",*(a+i)); printf("\n"); /*配列bへの読み込み*/ for(i=1;i<N+1;i++) scanf("%d",&*(b+i)); *b=0; printf("入力された数値:"); for(i=1;i<N+1;i++) printf("%d",*(b+i)); printf("\n"); /*配列resultの初期化*/ for(i=0;i<N+1;i++) *(result+i)=0; carry=0; /*result=a+bの演算*/ for(i=(N+1);i>=0;i--){ *(result+i)=*(a+i)+*(b+i)+carry; if(*(result+i)>=10){ *(result+i)-=10; carry=1; } else carry=0; } /*演算結果の表示*/ printf("和:"); for(i=0;i<N+1;i++) printf("%d",*(result+i)); printf("\n"); /*メモリ領域の解放*/ free(a); free(b); free(result); }

  • 関数のパラメータを配列に格納したいのですが

    #include<stdio.h> #include<stdlib.h> int func(int, int, int, int); int main(void) { int a = 3, b = 4, c = 5, d = 6; int sum; sum = func(a, b, c, d); printf("合計は%dです。\n", sum); return EXIT_SUCCESS; } int func(int m, int n, int o, int p) { int Hairetu[4]; int Sum = 0; int i; /* ここで、Hairetuにm, n, o, pを格納したい */ for(i=0; i<4; i++) Sum += Hairetu[i]; return Sum; } 例えばこのようなプログラムがあった時、m, n, o, pの値をHairetuに格納するには、どのようにすればよいのでしょうか。 分かりにくい文章ですが、どうかよろしくお願い致します。

  • (void *)と&の違い

    #include<stdio.h> void * func(void *p){ printf("□■□func開始□■□\n"); printf("pのアドレス = %p\n",p); printf("p = %d\n",(int)p); (int)p += 100; printf("p = %d\n",(int)p); printf("□■□func開始□■□\n"); return NULL; } int main(void){ int number = 30; printf("numberのアドレス = %p\n",&number); func((void *)number);★1 return 0; } -------------------------------------------------------------- #include<stdio.h> void * func(int *p){ printf("□■□func開始□■□\n"); printf("pのアドレス = %p\n",p); printf("p = %d\n",*p); *p += 100; printf("p = %d\n",*p); printf("□■□func開始□■□\n"); return NULL; } int main(void){ int number = 30; printf("numberのアドレス = %p\n",&number); func(&number);★2 return 0; } 上記の2つは同じ結果になるのですが★1と★2のそれぞれの違いがわかりません。どなたかご教授をお願いします。

  • ポインタと配列 助けてください

    #include <stdio.h> int main(void) { int a[5] = {1, 2, 3, 4, 0}; int i, *ptr; ptr = ######; while (*ptr != 0){ ######; ######; }      for (i = 0; i < 5; i++) printf("a[%d]=%2d &a[%d]=%p\n", i, #####,i, #####); putchar('\n'); ptr = ######; for (i = 0; i < 5; i++){ printf("ptr値 =%d ptrアドレス =%p \n", ####, ####); ####; } printf("\n"); return (0); } 一次元配列a[]の一番目の要素以外を0にするプログラム(ただし、最後の要素は0)を作成したいのですが、#の部分に何をあてはめたらいいかわかりません。 助けてください。

専門家に質問してみよう