牛、豚、鶏、どれか一つ食べられなくなるとしたら?

他人のコードに以下のようなものがありした。

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;
ではいけないのでしょうか?

あえて上記のように書く理由は何かありますか?

A 回答 (7件)

>具体的な理由を指摘していただけると幸いです。


構造体の仕様変更例
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])を示す意味では有りません。
今回のソケット通信では、構造体にセットしたデータを、指定されたバイト
数(構造体サイズ)単位で、通信を行っているようです。
    • good
    • 0
この回答へのお礼

具体的な例をいただき、さらに撤回していただき、よく理解できました。

質問した時点で、ソケット通信で何をしているかまで読み取れなかったものですみません。

結局読みにくいものの、正しいコード、ただ、仕様変更には向かない、ということですね。

お礼日時:2017/06/07 23:52

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言語というのは、そういうことをやるための言語なわけで。
    • good
    • 0
この回答へのお礼

批判している回答もありましたが、このように明快に答えてくださって、ある意味納得しました。
まずは、これでよいと思うことにして、もう少し深いところが分かっってきたらもう一度立ち止まってみます。

お礼日時:2017/06/08 22:09

>ところで、具体的には通信でどうやって構造体に入れれば良いのでしょうか?



通信の場合、相手と自分が同じエンディアンで動作している。
とは限りませんので、仕様の方でどっちに揃えましょうね。となっていることがあります。
0x12345678をバイト列として送る場合に0x78からなのか、0x12からなのか。というやつ。
ソケットだとその辺を解決するために、ホストバイトオーダーからネットワークバイトオーダーに変換する、ネットワークバイトオーダーからホストバイトオーダーに変換するという関数が用意されています。
ホストバイトオーダーとネットワークバイトオーダーご同じ環境なら実態はなにもしない関数で、異なる関数ではそれぞれ変換する処理が実行されます。


あとは…パディングと呼ばれる詰め物がどうなるか。でしょうかね。
    • good
    • 0
この回答へのお礼

ありがとうございました。

お礼日時:2017/06/08 22:10

普通の (ISO 規格に従った) C では


struct coma{
char a[5];
float b[20];
.....
}
というのは「struct coma」の定義であって, それだけではメモリを確保しない. つまりアドレスを持つことはない.

あとこれを通信で使うのはとても危険だなぁ. #3 はまだ控え目に「構造体の内容が異なる/変わった場合には通用しなくなる」って書いてるけど, 実際には処理系のオプションを 1つ変えるだけで動かなくなっちゃうからね.
    • good
    • 0
この回答へのお礼

うわわ、なんと初歩的なミス。
すみません。
当方、ほぼ25年ぶりにプログラミング、Cを扱ったもので、ポカが多いです。

ところで、具体的には通信でどうやって構造体に入れれば良いのでしょうか?

お礼日時:2017/06/07 23:48

>他人のコードに以下のようなものがありした。


現在は、たまたま動いているように見えるだけのプログラム。
構造体の内容が異なる/変わった場合には通用しなくなる上に、
プログラムの可読性も悪い、駄目なコーディング例。
    • good
    • 0
この回答へのお礼

ありがとうございました。

具体的な理由を指摘していただけると幸いです。
他人といっても、それなりの会社に発注したものなので、信頼できるものだと思っているのですが。

お礼日時:2017/06/07 22:09

確認だけど


char *p=(char *)(&coma);
の &coma でアドレスをとっている「coma」とやらはどのように宣言されているのでしょうか?

なお, 「構造体の要素をどのように配置するか」自体は確かに処理系に依存するけど
・書いてある順に配置する
・先頭要素のアドレスと構造体オブジェクトそのもののアドレスは一致する
という点は規格で規定されている.
    • good
    • 0
この回答へのお礼

comaの宣言は

上に書きましたが、何か問題がありましたか、もう少し長く書くと
struct coma{
char a[5];
float b[20];
.....
}

という感じです。

>なお, 「構造体の要素をどのように配置するか」自体は確かに処理系に依存するけど
>・書いてある順に配置する
>・先頭要素のアドレスと構造体オブジェクトそのもののアドレスは一致する
>という点は規格で規定されている.

あれ、そうなんですか。NO.1の方の解答をようやく理解したところでしたが、
次の解答をお待ちします。

なお、ソケット通信で受け取ったデータがpに入っていて、
それを comaに代入するための準備コードです。

お礼日時:2017/06/07 22:08

A1


>(&coma)はcoma[0]のアドレスなので
 comaが配列であるかどうかは質問文では判りませんね。

  どちらでも無い。
  構造体の要素をどのように配置するかは処理系に依存するので&comaと&coma.a[0]が同値と  は言えない。
  pの中にcomaのアドレスが入るとしか言えない。

A2 *pとcomaでは方が違うからエラーもしくは警告となる。
    • good
    • 0
この回答へのお礼

ありがとうございます。

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
だから違うということですね。

お礼日時:2017/06/07 22:08

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!