いつもお世話になっています。
角度を入力すると、
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も見ています
-
とっておきの「夜食」教えて下さい
真夜中に小腹がすいたときにこっそり作るメニュー、こっそり家を抜け出して食べに行くお店… 人には言えない、けど自慢したい、そんなあなたの「とっておきの夜食」を教えて下さい。
-
大人になっても苦手な食べ物、ありますか?
大人になっても、我慢してもどうしても食べれないほど苦手なものってありますよね。 あなたにとっての今でもどうしても苦手なものはなんですか?
-
「覚え間違い」を教えてください!
私はかなり長いこと「大団円」ということばを、たくさんの団員が祝ってくれるイメージで「大円団」だと間違えて覚えていました。
-
おすすめのモーニング・朝食メニューを教えて!
コメダ珈琲店のモーニング ロイヤルホストのモーニング 牛丼チェーン店の朝食などなど、おいしいモーニング・朝食メニューがたくさんありますよね。
-
タイムマシーンがあったら、過去と未来どちらに行く?
20XX年、ついにタイムマシーンが開発されました。 あなたは過去に行く? それとも未来? タイムマシーンにのって、どこに行って、何をしたいか教えてください!
-
関数から配列を返すには?
C言語・C++・C#
-
C# Listを使わずに2次元配列の動的確保をしたいです。
C言語・C++・C#
-
Functionの戻り値を2次元配列にする方法
Visual Basic(VBA)
-
-
4
unsigned long long 型のフォーマット指定子
C言語・C++・C#
-
5
Functionの戻り値を配列にしたいのですが
Visual Basic(VBA)
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/22】このサンタクロースは偽物だと気付いた理由とは?
- ・お風呂の温度、何℃にしてますか?
- ・とっておきの「まかない飯」を教えて下さい!
- ・2024年のうちにやっておきたいこと、ここで宣言しませんか?
- ・いけず言葉しりとり
- ・土曜の昼、学校帰りの昼メシの思い出
- ・忘れられない激○○料理
- ・あなたにとってのゴールデンタイムはいつですか?
- ・とっておきの「夜食」教えて下さい
- ・これまでで一番「情けなかったとき」はいつですか?
- ・プリン+醤油=ウニみたいな組み合わせメニューを教えて!
- ・タイムマシーンがあったら、過去と未来どちらに行く?
- ・遅刻の「言い訳」選手権
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列を使わずに、変数名を動的...
-
先頭アドレスとは何ですか?
-
テキストファイルから文字列を...
-
【速いブラインドタッチ】手を...
-
C# Listを使わずに2次元配列の...
-
C# 配列の変数宣言について。
-
unsigned char配列への入力の仕方
-
VBAで配列からbmp画像を出力す...
-
2次元配列を戻り値とする関数?
-
【C言語】配列の中に配列を入れ...
-
構造体配列を引数とするDLL作成...
-
CSVファイルのデータを2次元配...
-
プログラミングの課題で「5人分...
-
配列の配列?
-
配列で格納したものをmsgboxで...
-
C言語プログラミングで数あてゲ...
-
配列を含む構造体の初期値について
-
C言語で特定列だけを抽出して配...
-
C言語の配列のサイズ
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列を使わずに、変数名を動的...
-
先頭アドレスとは何ですか?
-
C# 配列の変数宣言について。
-
配列で格納したものをmsgboxで...
-
C# Listを使わずに2次元配列の...
-
VBで構造体の配列を関数に渡す...
-
テキストファイルから文字列を...
-
C言語で特定列だけを抽出して配...
-
Excel、VBAのユーザーフォーム...
-
【C言語】配列の中に配列を入れ...
-
配列を含む構造体の初期値について
-
unsigned char配列への入力の仕方
-
複数の選択範囲の行番号を個別...
-
【速いブラインドタッチ】手を...
-
配列の参照渡しで型が一致しま...
-
ExcelVBAで質問です。離れた二...
-
VB.NET 構造体の配列の検索機能...
-
VBでC言語のポインタみたい...
-
Redimした動的配列はEraseする...
おすすめ情報