C言語初心者です。
今回の質問は入力された構造体のメンバのデータを型の異なる構造体に代入したいのですが、毎回コンパイラにおこられてしまいます(汗)具体的には
typedef struct MSG{
longint type;
int flg;
int Dt[64];
}t_msg;
このDt[64]を以下の構造体に代入します。
typedef struct SC_MSG{
char a;
char b;
short c;
char d;
char e;
short f;
}t_sc_msg;
その際、異なる関数で処理するため、
main(){
foo(&t_msg);
};
void foo(t_msg *pt_msgdt){
t_sc_msg = (*pt_msgdt+8);
ココがエラーになってしまいます。
何か、根本的な間違いをおかしている気がします。
ご指導の方、宜しくお願いします。
ちなみにOSはLinuxでコンパイラーはgccです。
No.9ベストアンサー
- 回答日時:
>intの配列の中身はなんとゆったら良いかわかりませんが、0x00000001といったようなint型のリトルエンディアン型のデータです。
なるほど、バイナリデータを扱っているのですね。
実際のデータが分からないので、下記のように仮定します。
Dt[0] = 0x01234567;
Dt[1] = 0x89ABCDEF;
メモリ内のイメージは、リトルエンディアンなら、下記。
67 45 23 01
EF CD AB 89
構造体との対応を下記と仮定します。(Lは下位バイト、Hは上位バイト)
a b cL cH
d e fL fH
構造体に代入する処理は下記。
void foo(t_msg *pt_msgdt){
t_sc_msg sc_msg;
sc_msg.a = pt_msgdt->Dt[0] & 0xFF;
sc_msg.b = (pt_msgdt->Dt[0] >> 8) & 0xFF;
sc_msg.c = (pt_msgdt->Dt[0] >> 16) & 0xFFFF;
sc_msg.d = pt_msgdt->Dt[1] & 0xFF;
sc_msg.e = (pt_msgdt->Dt[1] >> 8) & 0xFF;
sc_msg.f = (pt_msgdt->Dt[1] >> 16) & 0xFFFF;
}
上記の様に、バイナリデータのフォーマットに従って、
一つ一つ地道に代入するのが確実だと思います。
(構造体から配列へ戻す関数も作る必要があるでしょう。)
===========================================================
別回答ですが、バイナリデータのフォーマットが、
実際の構造体の構造と一致するようでしたら、
型変換で解決するかもしれません。
あまり自信はないので、参考程度にして下さい。
パディングを無効化する必要があると思いますが、
gccには詳しくないので、下記の部分が gcc で通るかは不明です。
#pragma pack(1)
#pragma pack()
------------------------------------------------------------
#include <stdio.h>
typedef struct MSG{
long type;
int flg;
int Dt[64];
}t_msg;
//アライメントの制御
#pragma pack(1)
typedef struct SC_MSG{
char a;
char b;
short c;
char d;
char e;
short f;
}t_sc_msg;
#pragma pack()
void foo(t_msg *pt_msgdt){
t_sc_msg *sc_msg;
//型変換し、強引に代入(^^;
sc_msg = (t_sc_msg *)(pt_msgdt->Dt);
printf("%x \n",(int)sc_msg->a);
printf("%x \n",(int)sc_msg->b);
printf("%x \n",(int)sc_msg->c);
printf("%x \n",(int)sc_msg->d);
printf("%x \n",(int)sc_msg->e);
printf("%x \n",(int)sc_msg->f);
}
void main(){
t_msg msg;
msg.Dt[0] = 0x01234567;
msg.Dt[1] = 0x89ABCDEF;
foo(&msg);
}
------------------------------------------------------------
動作確認は下記のコンパイラで行いました。
Borland C++ 5.82 for Win32 Copyright (c) 1993, 2005 Borland
回答ありがとうございます。
上記のシフトの方でこれから組んでみようと思います。
とても親切に教えていただきありがとうございます。
No.11
- 回答日時:
★アドバイス
・以下のようなキャストをすればコピー可能と思います。
ただし、リトルエンディアン、ビッグエンディアンをきちんと考えて下さい。
// 変数の宣言(これ重要)
t_msg g_msg = { 0 };
t_sc_msg g_sc_msg = { 0 };
// メイン関数
int main( void )
{
foo( &g_msg );
return 0;
}
// 代入用の関数
void foo( t_msg *pt_msgdt )
{
g_sc_msg = *((t_sc_msg *)pt_msgdt->Dt);
}
以上。
No.10
- 回答日時:
単純に代入したい(転送したい)というなら、memcpyで転送できます。
転送サイズは、受け側にあわせて、受け側のサイズ分転送します。
t_sc_msg = (*pt_msgdt+8); を
memcpy(&t_sc_msg,pt_msgdt->Dt,sizeof(t_sc_msg));
とします。
但し、業務的にこれで良いかどうかは、質問者さまのみしか知りえませんので、質問さまのほうで、判断してください。
No.8
- 回答日時:
いっそのこと、代入用の関数作っちゃったら?
例えばこんなかんじで。
/**
関数名 Msg2CsMsg
概要 MSG型のデータをCS_MSG型のデータに代入する。
引数 *src 入力元となるMSG型データへのポインタ
*tgt 代入先となるCS_MSG型データの格納領域へのポインタ
戻り値 0 代入成功
-1 ポインタがNULL
*/
int Msg2CsMsg(MSG *src, CS_MSG *tgt)
{
if( NULL == src ) return -1;
if( NULL == tgt ) return -1;
// あとはどうなって欲しいか、そのとーりにかく。
// 変な小細工しないほうがデバッグしやすいでしょ。
return 0; // 代入完了。
}
回答ありがとうございます。
かれこれデバックもうまくいかずてんてこ舞いとなっています。
代入用の関数を作ってみたところ、やはりint型の配列にchar型の構造体は代入できないといったエラー文がきました。もう少し検討してみたいと思います。ありがとうございます。
No.7
- 回答日時:
No6回答者です。
他の回答への補足を見ていると、
No6の回答は的外れっぽいですね。
int Dt[64]のデータを、t_sc_msgへ代入したいとの事ですが、
intの配列を、構造体へ代入する時のルールが不明です。
intの配列には、何が入っているのでしょうか?
出来れば、具体的なデータを示して下さい。
----------------------------------------------------------
型は無視して、単純に上から順に代入?(^^;
void foo(t_msg *pt_msgdt){
t_sc_msg sc_msg;
sc_msg.a = pt_msgdt->Dt[0];
sc_msg.b = pt_msgdt->Dt[1];
sc_msg.c = pt_msgdt->Dt[2];
sc_msg.d = pt_msgdt->Dt[3];
sc_msg.e = pt_msgdt->Dt[4];
sc_msg.f = pt_msgdt->Dt[5];
}
----------------------------------------------------------
それとも、t_sc_msgのバイナリーデータを、
intの配列として保存しているような、複雑な内容でしょうか?
この回答への補足
回答ありがとうございます。
>intの配列には、何が入っているのでしょうか?
intの配列の中身はなんとゆったら良いかわかりませんが、0x00000001といったようなint型のリトルエンディアン型のデータです。
>intの配列として保存しているような、複雑な内容でしょうか?
何となく予想はついておられると思いますが、メッセージキューからレシーブする&T_MSGの構造体からDt[64]の中身を編集するといった内容です。
Dt[64]の中身を構造体に代入した方が編集しやすいと思ったのですが、うまく行きませんでした。宜しくお願い致します。
No.6
- 回答日時:
共用体を使うべき問題ではないでしょうか?
複数の種類のデータを持つ部分を共用体として宣言します。
-------------------------------------------------
typedef struct SC_MSG{
char a;
char b;
short c;
char d;
char e;
short f;
}t_sc_msg;
//共用体を宣言
typedef union UNION_DT{
int Dt[64];
t_sc_msg sc_msg;
} t_union_dt;
typedef struct MSG{
long type;
int flg;
t_union_dt u; //共用体を入れる
}t_msg;
//int の配列として処理する関数
void hoge(t_msg *pt_msgdt){
int *pdt;
pdt = pt_msgdt->u.Dt;
}
//t_sc_msgとして処理する関数
void foo(t_msg *pt_msgdt){
t_sc_msg sc_msg;
sc_msg = pt_msgdt->u.sc_msg;
}
void main(){
t_msg msg1, msg2;
hoge(&msg1);
foo(&msg2);
}
----------------------------------------------
共用体、構造体はアライメントの問題があります。
共用体を使った型変換は期待しない結果に終わる可能があります。
共用体は、型変換の為のものではなく、
あくまで複数の型を共存させる為のものです。
その点はご注意下さい。
アライメントに関しては下記など参考に。
http://www.g-ishihara.com/c_st_01.htm
No.5
- 回答日時:
>なんとかt_msg.Dt[64]だけ抜き出そうとしているのですが・・。
t_msg 型の変数 my_msg があったなら、my_msg.Dt[0], my_msg.Dt[1], ...
と順にアクセス可能です。
No.4
- 回答日時:
・エラーの原因をつかめていない以上、まずは完全なソースコードを投稿することをお薦めします。
・エラーメッセージを読みましょう。エラーの原因がおおまかとはいえ表示されるわけですから、読まない理由はありません。
というのがまずは一般論です。自分もC言語は学び始めたばかりですから、頑張ってその心を読んでみます。
>foo(&t_msg);
t_msgは型なので引数に渡せません。
f_msg bar;
foo(&bar);
という感じで書きたかったのでしょうか?
>*pt_msgdt+8
pt_msgdt型の値に+演算子をつかうことはできません。
もしかして、Dt[64]にアクセスしようとして*(pt_msgdt+8) と書きたかったでしょうか?そうだとしても、*(pt_msgdt+8)はDt[64]を指しません。もしかしたら (*pt_msgdt).Dt と
書きたかったのかもしれません。
>t_sc_msg = (*pt_msgdt+8);
t_sc_msg baz = (*pt_msgdt).Dt;と書きたかったのかもしれません。これも左右の型が異なるのでそのまま代入はできません。そもそも、Dtは int Dt[64] でおそらくSC_MSGよりサイズが大きいでしょうから、代入できたとしても入りきらないと思います。
char + char + short + char + char + short → (たぶん)64ビットだ! → int Dt[64]だと64ビット(!?)だからぴったり!という発想でしょうか?そもそも、配列のデータで一発で構造体を初期化しようとするというのが無理な発想かと思います。構造体のメンバは必ずしも連続したメモリに配置されないそうですから。構造体のアライメントとかいうヤツです。いろんなところが間違っている気がします。
参考URL:http://www.hyuki.com/writing/techask.html
早速の回答ありがとうございます。
>foo(&t_msg);
に関してはその通りです。端折りをして申し訳ございません。
>*pt_msgdt+8
ココは二番めの悩みでした。'->'を使用すると他のエラーが多発し、雰囲気的にuint32 とsint32 の次なので8byteずらせばDtの領域なのではないかと解釈しておりました。
>t_sc_msg = (*pt_msgdt+8);
ココが一番のなやみです。
単純にはt_msg.Dt[64]をt_sc_msg に先頭から代入したいということです。足りない分にはメンバを追加するという方法を取ります。
宜しくお願いします。
No.3
- 回答日時:
t_msg形のtype,flg,Dtを、t_sc_msg形のa,b,c,d,e,fへ代入する方法がコンパイラも回答者もわかりません。
type,flg,Dtを、a,b,c,d,e,fへ代入する方法を細かく教えてください。
この回答への補足
早速の回答ありがとうございます。
>t_msg形のtype,flg,Dtを、t_sc_msg形のa,b,c,d,e,fへ代入する方法がコンパイラも回答者もわかりません。
t_msgのDtのみを先頭からa,b,c,d,e,fにアドレスだけ渡して代入しようと考えてます。初歩的なことなのですがこれは不可能なのでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- C言語・C++・C# プログラムが書けません。 4 2023/01/22 22:57
- JavaScript javascriptで入力フォームが空欄の時にアラートによるエラーを出すコードを書いています。 2 2023/06/13 17:58
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- C言語・C++・C# C言語 共用体について コマンドライン引数で値を2つ入力したときに、argv[2]の値をUNI u1 4 2022/04/25 20:34
- JavaScript 入力フォームの javascript で メールアドレスの正規チェックをを行い、ボタンをクリックして 2 2022/04/27 16:06
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/22】このサンタクロースは偽物だと気付いた理由とは?
- ・お風呂の温度、何℃にしてますか?
- ・とっておきの「まかない飯」を教えて下さい!
- ・2024年のうちにやっておきたいこと、ここで宣言しませんか?
- ・いけず言葉しりとり
- ・土曜の昼、学校帰りの昼メシの思い出
- ・忘れられない激○○料理
- ・あなたにとってのゴールデンタイムはいつですか?
- ・とっておきの「夜食」教えて下さい
- ・これまでで一番「情けなかったとき」はいつですか?
- ・プリン+醤油=ウニみたいな組み合わせメニューを教えて!
- ・タイムマシーンがあったら、過去と未来どちらに行く?
- ・遅刻の「言い訳」選手権
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Integer変数をカラにしたいので...
-
VBAのプログラムで、DIAG = 1# ...
-
int型とchar型について
-
値が変わるのはどうしてでしょ...
-
VBAの変数のデータ型を変更する...
-
リッチテキストボックスの中身...
-
構造体のデータを丸ごとコピー...
-
構造体のポインタにNULLが入らない
-
aspでユーザー定義の構造体を作...
-
charとucharの違い
-
構造体の初期化方法について
-
typedefをプログラム中で解除す...
-
「#undef」と「#define」の使い...
-
異なる構造体のデータのコピー
-
C++ 構造体の一括初期化 {0}
-
VBAにてcolorindexを変数に格納...
-
この構造体の意味が分かりません。
-
C言語 配列の長さの上限
-
関数から配列を返すには?
-
init関数の意味
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBAのプログラムで、DIAG = 1# ...
-
Integer変数をカラにしたいので...
-
C++ 構造体の一括初期化 {0}
-
「#undef」と「#define」の使い...
-
C言語 構造体の中に共用体を定...
-
構造体のデータを丸ごとコピー...
-
値が代入されてない時
-
typedefをプログラム中で解除す...
-
charとucharの違い
-
異なる構造体のデータのコピー
-
構造体のポインタにNULLが入らない
-
VBAにてcolorindexを変数に格納...
-
long型のデータをバイト型の配...
-
VBAの変数のデータ型を変更する...
-
整数から16進数への変換 現在c...
-
構造体の初期化方法について
-
日付チェック関数について
-
1バイトデータの読み出しについて
-
GTKプログラミングで型宣言する...
-
命名規則 VB 構造体
おすすめ情報