他人のコードに以下のようなものがありした。
struct coma{
char a[5]......
}
char *p=(char *)(&coma);
Q1
(&coma)はcoma[0]のアドレスなので
(char *)(&coma)はcoma.a[0].のアドレスの中身、すなわちcoma.a[0]ということですか?
それともpのアドレスがcoma.a[0]のアドレスということですか?
Q2
おそらく、上記の解答は後者であるとして、
char *p=coma;
ではいけないのでしょうか?
あえて上記のように書く理由は何かありますか?
No.4ベストアンサー
- 回答日時:
>具体的な理由を指摘していただけると幸いです。
構造体の仕様変更例
struct coma{
int id; // 仕様追加
char a[5];
float b[20];
.....
}
コーディング内で、特定の構造体メンバー(coma[0])を示す目的で
>char *p=(char *)(&coma);
の様な使い方をしている場合には、それを知らないプログラマーが、上記の
様な構造体の仕様変更をした場合、動作不良を起こします。
#(char *)で、キャスト(型変換)しているので、コンパイル事にはエラー
#にならない。
>それなりの会社に発注したものなので
たまに頭が良い人が「自分にはこんなすごいテクニックを駆使したプログ
ラムが作れるんだ!!」と言わんばかりに自慢げに作ったプログラムの中
には、並のプログラマーには十分理解できず修正・変更ができない、又は解釈
を間違えた結果、トラブルを起こす場合が有ります。
#一般的な注意点。今回分はNo2へのお礼が有ったので撤回します。
No.2の回答へのお礼
>なお、ソケット通信で受け取ったデータがpに入っていて、
>それを comaに代入するための準備コードです。
できれば、これを先に出して欲しかった...
これだと、coma構造体の先頭アドレスを、char *pに渡す意味になります。
特定の構造体メンバー(coma[0])を示す意味では有りません。
今回のソケット通信では、構造体にセットしたデータを、指定されたバイト
数(構造体サイズ)単位で、通信を行っているようです。
具体的な例をいただき、さらに撤回していただき、よく理解できました。
質問した時点で、ソケット通信で何をしているかまで読み取れなかったものですみません。
結局読みにくいものの、正しいコード、ただ、仕様変更には向かない、ということですね。
No.7
- 回答日時:
struct coma_t{
char a[5]......
}coma;
ということですかね。
Q1
少なくとも前者は明らかに間違いです。
後者も、
>pのアドレスがcoma.a[0]のアドレス
ではなくて、pがcoma.a[0]のアドレス、が正しいです。
Q2
> char *p=coma;
やってみればすぐわかりますが、それではコンパイルエラーになりますから、いいわけないですね。。
> char *p=(char *)(&coma);
批判している回答もありますが、私は、この書き方は、C言語であれば、構造体の中身をバイト単位でアクセスする最も真っ当な書き方で、批判されるような点は何もないと思います。
もちろん、構造体の中身にバイト単位でアクセスするという設計自体の是非はあるのかもしれませんが、そもそも、C言語というのは、そういうことをやるための言語なわけで。
批判している回答もありましたが、このように明快に答えてくださって、ある意味納得しました。
まずは、これでよいと思うことにして、もう少し深いところが分かっってきたらもう一度立ち止まってみます。
No.6
- 回答日時:
>ところで、具体的には通信でどうやって構造体に入れれば良いのでしょうか?
通信の場合、相手と自分が同じエンディアンで動作している。
とは限りませんので、仕様の方でどっちに揃えましょうね。となっていることがあります。
0x12345678をバイト列として送る場合に0x78からなのか、0x12からなのか。というやつ。
ソケットだとその辺を解決するために、ホストバイトオーダーからネットワークバイトオーダーに変換する、ネットワークバイトオーダーからホストバイトオーダーに変換するという関数が用意されています。
ホストバイトオーダーとネットワークバイトオーダーご同じ環境なら実態はなにもしない関数で、異なる関数ではそれぞれ変換する処理が実行されます。
あとは…パディングと呼ばれる詰め物がどうなるか。でしょうかね。
No.5
- 回答日時:
普通の (ISO 規格に従った) C では
struct coma{
char a[5];
float b[20];
.....
}
というのは「struct coma」の定義であって, それだけではメモリを確保しない. つまりアドレスを持つことはない.
あとこれを通信で使うのはとても危険だなぁ. #3 はまだ控え目に「構造体の内容が異なる/変わった場合には通用しなくなる」って書いてるけど, 実際には処理系のオプションを 1つ変えるだけで動かなくなっちゃうからね.
うわわ、なんと初歩的なミス。
すみません。
当方、ほぼ25年ぶりにプログラミング、Cを扱ったもので、ポカが多いです。
ところで、具体的には通信でどうやって構造体に入れれば良いのでしょうか?
No.2
- 回答日時:
確認だけど
char *p=(char *)(&coma);
の &coma でアドレスをとっている「coma」とやらはどのように宣言されているのでしょうか?
なお, 「構造体の要素をどのように配置するか」自体は確かに処理系に依存するけど
・書いてある順に配置する
・先頭要素のアドレスと構造体オブジェクトそのもののアドレスは一致する
という点は規格で規定されている.
comaの宣言は
上に書きましたが、何か問題がありましたか、もう少し長く書くと
struct coma{
char a[5];
float b[20];
.....
}
という感じです。
>なお, 「構造体の要素をどのように配置するか」自体は確かに処理系に依存するけど
>・書いてある順に配置する
>・先頭要素のアドレスと構造体オブジェクトそのもののアドレスは一致する
>という点は規格で規定されている.
あれ、そうなんですか。NO.1の方の解答をようやく理解したところでしたが、
次の解答をお待ちします。
なお、ソケット通信で受け取ったデータがpに入っていて、
それを comaに代入するための準備コードです。
No.1
- 回答日時:
A1
>(&coma)はcoma[0]のアドレスなので
comaが配列であるかどうかは質問文では判りませんね。
どちらでも無い。
構造体の要素をどのように配置するかは処理系に依存するので&comaと&coma.a[0]が同値と は言えない。
pの中にcomaのアドレスが入るとしか言えない。
A2 *pとcomaでは方が違うからエラーもしくは警告となる。
ありがとうございます。
Q1とQ2に沿って解答くださり助かります。
A1
>>(&coma)はcoma[0]のアドレスなので
> comaが配列であるかどうかは質問文では判りませんね。
すみません。会社のPCから打てず、スマホで打ち込んだため間違えました。
>>(&coma)はcoma.a[0]のアドレスなので
と書くつもりでした。
>構造体の要素をどのように配置するかは処理系に依存するので&comaと&coma.a[0]が同値と は言えない。
そうなんですか。それは分かっておりませんでした。
きちんと動いているのは、Visual C++では同値だからなのか、たまたま同値になったのか???
では、mchar *p=(char *)(&coma.a[0]);
と書けばよいのでしょうか?
A2
*pはcharのポインタ
comaはstruct
だから違うということですね。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBAのプログラムで、DIAG = 1# ...
-
C言語 構造体の中に共用体を定...
-
Integer変数をカラにしたいので...
-
typedefをプログラム中で解除す...
-
VBAにてcolorindexを変数に格納...
-
異なる構造体のデータのコピー
-
「#undef」と「#define」の使い...
-
1バイトデータの読み出しについて
-
整数から16進数への変換 現在c...
-
charとucharの違い
-
仮想基底クラスをもつクラスの...
-
C++ 構造体の一括初期化 {0}
-
構造体のポインタにNULLが入らない
-
値が代入されてない時
-
VBAの変数のデータ型を変更する...
-
構造体
-
関数から配列を返すには?
-
C言語 配列の長さの上限
-
VB.NETでファイル名順にファイ...
-
System.IO.Directory.GetFiles...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBAのプログラムで、DIAG = 1# ...
-
Integer変数をカラにしたいので...
-
C++ 構造体の一括初期化 {0}
-
「#undef」と「#define」の使い...
-
構造体のデータを丸ごとコピー...
-
C言語 構造体の中に共用体を定...
-
VBAにてcolorindexを変数に格納...
-
値が代入されてない時
-
typedefをプログラム中で解除す...
-
VBAの変数のデータ型を変更する...
-
long型のデータをバイト型の配...
-
異なる構造体のデータのコピー
-
charとucharの違い
-
整数から16進数への変換 現在c...
-
構造体のポインタにNULLが入らない
-
日付チェック関数について
-
VBAで符号無し整数
-
ユーザー定義型変数の一括初期化
-
値が変わるのはどうしてでしょ...
-
命名規則 VB 構造体
おすすめ情報