固定要素数の行列の処理ですが、subでセグメントエラーを起こしています。
アドレスを出力してみると、subでは元々確保したアドレスでは無いところを指しています。
呼び出し側では「行列の先頭のアドレス」を明示したつもりだったのですが、どこが間違っているのでしょうか。少し長いですが、ソースコードと出力を示します。
typedefのところとsubのIFは変更できないので、double[3][3]とdouble** のIFを合わせないといけないのですが、合わせ方がよくわかりません。
よろしくお願いします。
=========================================
#include <stdio.h>
#include <string.h>
typedef double Matrix[3][3];
void sub( const double** mat );
int main(void)
{
int ret = 0;
int i, j;
Matrix mat = { { 0., 1., 2. },
{ 3., 4., 5. },
{ 6., 7., 8. } };
for( i = 0; i < 3; i++ ){
for( j = 0; j < 3; j++ ){
printf( "main : mat[%d][%d] = %f\n", i, j, mat[i][j] );
printf( "main : &mat[%d][%d] = %p\n", i, j, &mat[i][j] );
}
}
printf( "\n" );
sub( &mat[0][0] );
return ret;
}
void sub( const double** mat )
{
int i, j;
printf("---- &mat = %p\n", &mat );
for( i = 0; i < 3; i++ ){
for( j = 0; j < 3; j++ ){
printf( "sub : mat[%d][%d] = %f\n", i, j, mat[i][j] );
printf( "sub : &mat[%d][%d] = %p\n", i, j, &mat[i][j] );
}
}
printf( "\n" );
}
=========================================
main : mat[0][0] = 0.000000
main : &mat[0][0] = 0x7ffffca7bca0
main : mat[0][1] = 1.000000
main : &mat[0][1] = 0x7ffffca7bca8
main : mat[0][2] = 2.000000
main : &mat[0][2] = 0x7ffffca7bcb0
main : mat[1][0] = 3.000000
main : &mat[1][0] = 0x7ffffca7bcb8
main : mat[1][1] = 4.000000
main : &mat[1][1] = 0x7ffffca7bcc0
main : mat[1][2] = 5.000000
main : &mat[1][2] = 0x7ffffca7bcc8
main : mat[2][0] = 6.000000
main : &mat[2][0] = 0x7ffffca7bcd0
main : mat[2][1] = 7.000000
main : &mat[2][1] = 0x7ffffca7bcd8
main : mat[2][2] = 8.000000
main : &mat[2][2] = 0x7ffffca7bce0
---- &mat = 0x7ffffca7bc68
セグメンテーション違反です
No.14
- 回答日時:
ANo.8 の回答をしたものです。
「ANo.5 が正解」と書きましたが,場合によっては正解ではないかもしれません。
コンパイル時・実行時にエラーにならなくても,意味的に間違っている可能性はあります。
例えば,要素を格納する順番までは,引数の型だけでは分からないので。
列方向優先で格納することも比較的よくあります。
とにかく,
sub 関数がどういうデータを要求しているか,よく確認して下さい。
そして,それに合ったデータを用意してあげてください。
# 全要素のコピーが必要になるかも
何度もご回答、ありがとうございます。
既存の(自分が作ったものではない)関数を使う時は、おっしゃる通りの確認が必要ですね。間違えないように気をつけます。
No.13
- 回答日時:
A No.6の者ですが、ちょっと間違っていたので補足です。
double (*mat)[3];
mat = (double (*)[3])mat_;
が正しいですね。Matrixにキャストしても意味が無い(--;
それから、呼び出し側もとりあえず、
sub( (const double **)mat );
で動きます。(gcc -Wall では)
キャストで逃げるのは邪道な気はしますが、事情があれば仕方ないですね。
No.12
- 回答日時:
> 以下のワーニングがでています(Borland)。
質問そのものへの回答は既に他の方が挙げられていますのでほぼ解決していると思いますが、この警告が「何を言っているか」は理解していますか?
ご回答、ありがとうございます。
警告の内容は、「ポインタに変換した型が一致していない疑いあり」という感じでしょうか。sub内ではポインタのポインタとして引数を扱わないといけないのに、呼び出しで指定したポインタは、(単なる最初の要素へのポインタということで)シングルポインタになっているから合っていない、と言われているのかと理解しました。
No.11
- 回答日時:
エラー? と思ったので gcc で確認してみた
Matrix mat = {{ 0., 1., 2. },
{ 3., 4., 5. },
{ 6., 7., 8. }};
double *m[] = {mat[0], mat[1], mat[2]};
として
sub(m);
エラーなしで一応動作するけど?
それから、私も既存ライブラリにインタフェース合すということは良くあるので、今回もそうだろうと思いましたが、そういう事は最初に書いておくべきでしたね。
ご回答、ありがとうございます。
そのままコピペさせていただきましたが、なぜか、Borlandではエラーが出ます…。
質問の仕方は、今後気をつけます。
No.8
- 回答日時:
>呼び出し側では「行列の先頭のアドレス」を明示したつもりだったのですが、どこが間違っているのでしょうか。
「間違っている」というより、せっかく typedef したのだから、const double** はないような。
typedef const double Matrix[3][3];
void sub( Matrix mat ); // プロトタイプ
・
・
sub( mat ); // 関数呼び出し
・
・
void sub( Matrix mat ) // 関数本体
・
でエラーは出ませんよ。
ご回答ありがとうございます。
おっしゃる通りで、ご回答の通りにしたいのですが、大人の事情(No.7の方へのお礼に記載
)でそういうわけにもいかなくなったのです。
No.7
- 回答日時:
main では
sub((void *)mat);
のように void * に変換して逃げ, sub で
void sub( const double** mat_ )
{
Matrix *mat = (const void *)mat_;
/* 以下略 */
とするかなぁ.... そもそも「subのIFは変更できない」という条件がなぜ付いているのか理解できないのだが.
ご回答ありがとうございます。
voidポインタってこういう時に威力を発揮するのですね!
今回の問題は、typedefの方は相手の承認を得てしまっているのでもう変更できない、subの方は既存の実績ある関数で、これをそのまま使おうという方針になったことが発端なのです。
No.6
- 回答日時:
double ** は、double * へのポインタなので、
double * の指す先に何が入っているのか、コンパイラには
判断がつきません。
今回の場合は、double A[3][3]; と、サイズが分かっているので、
以下の様に、配列サイズを教えてあげる必要があります。
void sub( const double** mat_)
{
int i, j;
double (*mat)[3];
mat = (Matrix)mat_;
printf("---- &mat = %p\n", &mat );
...
みたいな感じかな。
ご回答ありがとうございます。
最初の[]以外の配列サイズは教えてあげる必要があることは理解しました。
mat = (Matrix)mat_;
のところで、Incompatible type conversion とエラーが出た(Borland)のですが、なんとか動くようにがんばってみます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語でユーザ関数を利用して複素数のべき乗と絶対値の数列を計算するプログラムが作りたいです。 3 2023/01/29 22:13
- C言語・C++・C# C 言語の Gauss Jordan 法について 2 2022/12/28 11:16
- C言語・C++・C# プログラミングペーパーテスト 次の問題の実行結果を答えろ #include int x[ ] = { 1 2022/06/16 21:49
- C言語・C++・C# Cのdoubleの浮動小数点表示について 3 2023/04/17 13:14
- C言語・C++・C# プログラミングの授業のペーパーテスト 実行結果を答えろ #include int x[ ] = {1 3 2022/06/16 20:08
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- C言語・C++・C# C言語: ポインタ 5 2022/06/01 08:33
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
プログラムでの数字につく”f”の...
-
C言語の型による処理速度の違い
-
C言語を実行すると-infが出てき...
-
doubleは常に%lfとするべきなのか
-
プログラミングについての質問
-
関数におけるif文とreturn文に...
-
float?数字の後にLがつくもの
-
doubleの変数にintとintの割り...
-
c言語のコンパイルエラー canno...
-
浮動小数点数が表示されないん...
-
はさみうち法のプログラム(C言...
-
方程式を2分法を用いて解くプロ...
-
C 開放してるのにエラー(doubl...
-
float型とdouble型の変数の違い...
-
C言語
-
c++,visual studioで積分のプロ...
-
C言語のpow関数の不具合
-
DWORDの警告
-
至急です! マクロ定義で #defi...
-
2分法で方程式の複数の解を自...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
プログラムでの数字につく”f”の...
-
float型とdouble型の変数の違い...
-
doubleの変数にintとintの割り...
-
C言語を実行すると-infが出てき...
-
C 開放してるのにエラー(doubl...
-
至急です! マクロ定義で #defi...
-
c言語で、繰り返し文の中で、0....
-
関数におけるif文とreturn文に...
-
C言語 関数プロトタイプ宣言の...
-
C言語初心者 構造体 課題について
-
C言語の型による処理速度の違い
-
Cで3乗根を求める方法
-
C言語で-23乗を取り扱うには
-
2分法で方程式の複数の解を自...
-
doubleは常に%lfとするべきなのか
-
c言語のコンパイルエラー canno...
-
C言語で直角三角形の斜辺を求め...
-
C言語のプログラムで#include<m...
-
int とdoubleの比較
-
C++で外積
おすすめ情報