![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?a65a0e2)
いつもお世話になっています。
角度を入力すると、
2×2の2次元配列を戻す
関数を作りたいのですが、
コンパイルすると、
戻り値の型のところで、
不正な変換だというエラーが出て
うまく行きません。
参考書を何度も読み直して
戻り値の型をポインタのポインタにするなど、
いろいろトライしてみたのですが、うまく行きません。
typedef を使う方法も考えましたが、
他にもっとすっきりする方法はないでしょうか?
どなたか参考URLをお教えくださるか、
解決策を教えてください。
よろしくお願いします。
ちなみに、この関数は大凡下記の通りです。
double** Matrix(double sita)
{
double mat[2][2];
mat[0][0]= cos(sita);
mat[0][1]= sin(sita);
mat[1][0]=-sin(sita);
mat[1][1]= cos(sita);
return mat;
}
No.4ベストアンサー
- 回答日時:
補足です。
もし、配列にこだわらないのであれば構造体を宣言してその値を返すようにした方が良いかもしれませんね。
struct mat_str {
:(配列でも、それぞれ意味のある変数でもOK)
};
struct mat_str Matrix (double sita)
{
struct mat_str mat;
:
return mat;
}
呼び出し側は、
struct mat_str result;
result = Matrix(1.0);
で、Matrix内のauto変数の値が 呼び出し側の resultに代入されます。
typedef struct mat_str stMat;
とすれば見やすくなりますね。
No.15
- 回答日時:
> int b[2][3];
> b=p
> を行ったところ、
> 型変換できないというコンパイルエラーになりました。
> つまり、この代入は、一方通行のようなのですが、
> これは、何故なのでしょうか?
b は配列変数のアドレスを表しているので、b に何か代入しようというのは、例えば int a と宣言された変数 a に対し、&a = p という代入をするのと同じことなのです。
変数自身のアドレスというのは、例外なく全てが「定数ポインタ」なので、アドレスへの代入はコンパイル時にエラーとなります。
例えば int a と宣言した a のアドレス &a の型は int * const です。
ここでの const は、ポイント先のデータではなく、&a 自身にかかります。
ポイント先である *&a(つまり a )は変更できますが、&a は const なので変更できません。
同様に上記の b の型は、int (* const)[3] です。
b 自身が const であるため、b への代入はできないのです。
leaz024様
アドバイスありがとうございます。
おかげさまで、
ポインタと配列に関して深い理解が得られました。
本当に助かりました。
今後ともよろしくお願いします。
No.14
- 回答日時:
配列とポインタで困っているところに追い討ちをかけてしまいますが
「配列を返す関数」を定義することはできません。
下のMatrix1はコンパイルに失敗します。
#include <stdio.h>
#include <math.h>
typedef double matrix_t1[2][2];
/*
matrix_t1 Matrix1(double th)
{
double s = sin(th);
double c = cos(th);
matrix_t1 m;
m[0][0] = c;
m[0][1] = s;
m[1][0] = -s;
m[1][1] = c;
return m;
}
*/
typedef struct { double v[2][2]; } matrix_t2;
matrix_t2 Matrix2(double th)
{
double s = sin(th);
double c = cos(th);
matrix_t2 m;
/*printf("%p\n", &m); */
m.v[0][0] = c;
m.v[0][1] = s;
m.v[1][0] = -s;
m.v[1][1] = c;
return m;
}
void main() {
matrix_t2 m = Matrix2(1);
/*printf("%p\n", &m); */
printf("%g %g\n%g %g\n", m.v[0][0], m.v[0][1], m.v[1][0], m.v[1][1]);
}
happy_people様
アドバイスありがとうございます。
サンプルプログラムまで
教えていただいてとても助かりました。
早速やってみます。
今後ともよろしくお願いします。
No.13
- 回答日時:
二次元配列へのポインタについてアドバイスを。
二次元配列 int a[2][3] があった時、この変数 a へのポインタ p の宣言は int (*p)[3] であり、int *p ではありません。
これは a が要素数情報を持つポインタであるのに対し、int * で宣言された p にはそれがないからです。
この要素数情報は型に含まれており、このため a と p は型があわず、代入しようとするとエラーとなるのです。
要素数情報を理解するには、次の「配列とポインタの関係」を見てください。
配列とその配列へのポインタとの関係は非常に簡単です。
int a[10];
int *p;
p = a; // p と a は同じ int * 型なので、代入しても問題ない。
p[3] = 5; // a[3] = 5 と同じ。
この関係は、二次元配列になっても同じです。
int a[2][3];
// a へのポインタ p の宣言
p = a; // 問題なく代入できるためには、p と a は同じ型でなければならない。
p[1][0] = 7; // a[1][0] = 7 と同じ。二次元配列へのポインタなのだから、できて当然。
a の型が int * なら、p の宣言は int *p で良いはずですね。
この時 p[1][0] という指定で、正しく a[1][0] にアクセスできるでしょうか?
答えは「否」です。
二次元配列 a の場合、一次元目(右側)の要素数が3個と分かっているので、a[1][0] とするだけで4番目のデータにアクセスできますが、p にはそれがないので、p[1][0] というアクセスができないのです。
確かに p[4] とすれば a[1][0] にアクセスすることもできますが、この方法には何のメリットもありません。一部の入門者が面白いと思うだけです。
a は3個の要素をもつ配列の配列なので、型は int (*)[3] となります。
この型で変数を宣言すればよいので、p の宣言は int (*p)[3] となります。(*p を囲むカッコは必須)
こうすることで *p のサイズは12バイト(正しくはintデータ3つ分)となり、p[n][m] というアクセスが可能となるのです。
(つまり、(*(p+n))[m] あるいは、*(*(p+n)+m) として解釈されます。)
この回答への補足
アドバイスありがとうございます。
1点だけ、分からない点があるので、
教えていただければありがたいです。
上の例で、
p=a
で受け取った後、
pは、あたかもaと全く同じように
配列操作が行えることが確認できました。
にもかかわらず、
int b[2][3];
b=p
を行ったところ、
型変換できないというコンパイルエラーになりました。
つまり、この代入は、一方通行のようなのですが、
これは、何故なのでしょうか?
よろしくお願いします。
leaz024様
アドバイスありがとうございます。
曖昧に理解していた部分が
厳密に理解できて、とても助かりました。
特に、配列の場合、列数を明示しないと
受け取れないという「しくみ」が良くわかりました。
前に参考書で見たような気がしたのですが、
上記のように丁寧には書かれていなかったので、
とても勉強になりました。
これを応用して、
3次元配列(a[2][3][4])の場合を
試行したところ、
int (*p)[3][4]
p = a
でばっちりうまく行きました。
n次元でも大丈夫そうです。
本当にありがとうございました。
No.12
- 回答日時:
>*(mat+0) と mat[0][0]
>は同じではありません。
>mat[0] ならば同じなのですが。
はい そのとおりです。
メモリ上の話と同じということです。
読み替えてください ませ
main()
{
double mata[2][2];
double *matb;
matb = malloc(sizeof(double) * 2 * 2);
Matrix(&mata[0][0] ,90);
Matrix(matb ,90);
};
No.10
- 回答日時:
おかしいなぁー
return &mat[0][0];
でどうでしょう(悔しい)
但し、私の方法だとエラーはでない思います(voidにしたので)
void Matrix(double *mat ,double sita)
{
*(mat+0)= cos(sita);
*(mat+1)= sin(sita);
*(mat+2)=-sin(sita);
*(mat+3)= cos(sita);
return;
};
これは、yatokesa様の
void Matrix (double mat[2][], double sita)
mat[0][0]= cos(sita);
mat[0][1]= sin(sita);
mat[1][0]=-sin(sita);
mat[1][1]= cos(sita);
}
とまったく同じです(好みの差です)
*(mat+0)はmat[0][0]
*(mat+1)はmat[0][1]
*(mat+2)はmat[1][0]
*(mat+3)はmat[1][1]
No.9
- 回答日時:
> double tt[2][2];
>tt=Matrix(PI/2);
呼び出し側のauto変数に配列として代入したいのなら、素直に呼び出し側の領域(tt)を渡した方が良いのではないでしょうか?
void Matrix (double mat[2][], double sita)
mat[0][0]= cos(sita);
mat[0][1]= sin(sita);
mat[1][0]=-sin(sita);
mat[1][1]= cos(sita);
}
関数は1つの値しか返せませんので、呼び出し側で用意した配列(複数の領域)に代入するようなコーディングはできないんです。
戻り値としてコーディングしたいのなら、先の私の補足のように struct として一つの領域にしてやりとりをすることをお薦めします。
yatokesa様
アドバイスありがとうございます。
上記の方法が呼び出し側での取り扱い
コーディング量から考えて
一番良さそうな気がしてきました。
おかげさまで、いろいろな方法で
解決できる目処が立ちました。
お忙しい中、
ご教示ありがとうございました。
No.8
- 回答日時:
> double tt[2][2];
> tt=Matrix(PI/2);
> のように配列変数のままにすると
> 型変換不能でコンパイルエラーになります。
配列は一種の「定数」であって「変数」ではありませんから、
そこへ何かを代入するという操作はできません。
> 何か良い方法がありましたら、
> 教えていただければありがたいです。
そのような方法は無いと思います。・・・というか、配列
変数にこだわらないのが良い方法だと思います。
ranx様
分かりました。
データは得られていますので、
あまり形式にこだわらず作業を続けることにします。
本当に助かりました。
どうもありがとうございました。
No.7
- 回答日時:
これは変ですねぇー
ファイルの拡張子は'.C'ですか? '.CC'ですか?
'.CC'なら'.C'でコンパイルしてください
nagare様
アドバイスありがとうございます。
ファイルは、CCですが、
クラス等を使っているので、
Cでのコンパイルは
エラーがたくさん出て、
うまく行きませんでした。
そこで、Unix(Compaq)でやってみたのですが、
やはり、コンパイルで型変換エラーが出ました。
ranx様の方法にした場合は、
うまく行きました。
nagare様の方法は非常にシンプルで
個人的には、この形で実現できたら
とても良いと思っていますので、
今後の検討課題にしたいと思います。
当面、yotaka様やranx様の方法で
対応していこうと思います。
いろいろとご教示ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- C言語・C++・C# C++のcinの動作 5 2023/02/26 00:13
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- 数学 単振り子とルンゲ・タック法 1 2022/07/15 00:05
- Visual Basic(VBA) Excel のユーザー定義関数でソルバーが動作しない 1 2022/09/05 19:51
- JavaScript カラーミーショップのsectionループ内で、[引数][戻り値]ありの関数的な処理を行いたいです。 1 2022/05/07 19:39
- Visual Basic(VBA) VBAでのMATCH関数 3 2022/10/17 19:06
- Perl perlで2次元配列をサブルーチンに値渡しで渡す 5 2022/12/17 18:49
- Excel(エクセル) ExcelのIF関数について 4 2023/05/24 12:54
このQ&Aを見た人はこんなQ&Aも見ています
-
見学に行くとしたら【天国】と【地獄】どっち?
みなさんは、一度だけ見学に行けるとしたら【天国】と【地獄】どちらに行きたいですか? 理由も聞きたいです。
-
いちばん失敗した人決定戦
あなたの「告白」での大失敗を教えてください。
-
みんなの【マイ・ベスト積読2024】を教えてください。
積読、ついついしちゃいませんか?そこでみなさんの 「2024年に買ったベスト積読」を聞きたいです。
-
コーピングについて教えてください
皆さんはストレスを感じたとき、どのような方法や手段、テクニックで対処していますか?
-
【お題】斜め上を行くスキー場にありがちなこと
運営も客も一流を通り越して斜め上を行くスキー場にありがちなことを教えて下さい。
-
関数から配列を返すには?
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・一番好きなみそ汁の具材は?
- ・泣きながら食べたご飯の思い出
- ・「これはヤバかったな」という遅刻エピソード
- ・初めて自分の家と他人の家が違う、と意識した時
- ・いちばん失敗した人決定戦
- ・思い出すきっかけは 音楽?におい?景色?
- ・あなたなりのストレス発散方法を教えてください!
- ・もし10億円当たったら何に使いますか?
- ・何回やってもうまくいかないことは?
- ・今年はじめたいことは?
- ・あなたの人生で一番ピンチに陥った瞬間は?
- ・初めて見た映画を教えてください!
- ・今の日本に期待することはなんですか?
- ・集中するためにやっていること
- ・テレビやラジオに出たことがある人、いますか?
- ・【お題】斜め上を行くスキー場にありがちなこと
- ・人生でいちばんスベッた瞬間
- ・コーピングについて教えてください
- ・あなたの「プチ贅沢」はなんですか?
- ・コンビニでおにぎりを買うときのスタメンはどの具?
- ・おすすめの美術館・博物館、教えてください!
- ・【お題】大変な警告
- ・洋服何着持ってますか?
- ・みんなの【マイ・ベスト積読2024】を教えてください。
- ・「これいらなくない?」という慣習、教えてください
- ・今から楽しみな予定はありますか?
- ・AIツールの活用方法を教えて
- ・最強の防寒、あったか術を教えてください!
- ・歳とったな〜〜と思ったことは?
- ・モテ期を経験した方いらっしゃいますか?
- ・好きな人を振り向かせるためにしたこと
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・これまでで一番「情けなかったとき」はいつですか?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語 配列の長さの上限
-
複数の選択範囲の行番号を個別...
-
銀行ATMの数字キーの配列
-
C# 配列の変数宣言について。
-
配列を使わずに、変数名を動的...
-
テキストファイルから文字列を...
-
配列の参照渡しで型が一致しま...
-
配列で格納したものをmsgboxで...
-
C# Listを使わずに2次元配列の...
-
VBでC言語のポインタみたい...
-
配列同士の文字列の比較
-
配列を含む構造体の初期値について
-
C言語初心者 ポインタについて...
-
2次元配列を戻り値とする関数?
-
Visual C++で配列を動的に確保...
-
市販のビンゴカードについて
-
VB.NET 構造体の配列の検索機能...
-
先頭アドレスとは何ですか?
-
ヘッダーファイルからの取り込...
-
整数型の配列をランダムに並べ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列を使わずに、変数名を動的...
-
配列で格納したものをmsgboxで...
-
テキストファイルから文字列を...
-
C# 配列の変数宣言について。
-
C# Listを使わずに2次元配列の...
-
先頭アドレスとは何ですか?
-
C言語で特定列だけを抽出して配...
-
【速いブラインドタッチ】手を...
-
配列の参照渡しで型が一致しま...
-
unsigned char配列への入力の仕方
-
ExcelVBAで質問です。離れた二...
-
VBで構造体の配列を関数に渡す...
-
複数の選択範囲の行番号を個別...
-
C++ vectorに配列をプッシュしたい
-
【C言語】配列の中に配列を入れ...
-
配列をEraseしてもメモリが開放...
-
Excel、VBAのユーザーフォーム...
-
Redimした動的配列はEraseする...
-
VB.NET 構造体の配列の検索機能...
おすすめ情報