質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

6回答

6048閲覧

【C言語】構造体データを別の構造体へコピーする方法

watan

総合スコア13

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2018/08/29 08:01

編集2018/08/29 23:21

C言語で構造体のデータを別の構造体へコピーする方法を教えてください。

コピー先の構造体はコピー元となる構造体に変数が追加されたものになります。

typedef struct{ char sStr0[4]; /* sStr0[9]ではなくStr0[4]の間違いでした*/ char sStr1[4]; char sStr2[4]; }stTest1 ; typedef struct{ char sStr0[4]; char sStr1[4]; char sStr2[4]; int iVal1 ; int iVal2 ; }stTest2 ; //ダミーデータ void main(){ stTest1 kFrom[3] = { {"001","AAA","111"}, {"002","BBB","222"}, {"003","CCC","333"} }; stTest2 kCopy[3] ; for( iLp = 0; iLp < 3; iLp++ ){ /* sStr0, sStr1, sStr2 はkFromのデータをそのままコピーしたい */ kCopy[iLp].iVal1 = iLp+1 ; kCopy[iLp].iVal2 = iLp+2 ; } return ; }

結果として、kCopyに

{"001","AAA","111", 0, 1} {"002","BBB","222", 1, 2} {"003","CCC","333", 2, 3}

としたいです。
sStr0,sStr1,sStr2を項目一つずつする以外に構造体ごとコピーできる方法があれば教えてください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答6

0

c

1typedef struct{ 2 char sStr0[9]; 3 char sStr1[4]; 4 char sStr2[4]; 5}stTest1 ; 6 7typedef struct{ 8 char sStr0[4]; 9 char sStr1[4]; 10 char sStr2[4]; 11 int iVal1 ; 12 int iVal2 ; 13}stTest2 ;

c

1typedef struct{ 2 char sStr0[9]; 3 char sStr1[4]; 4 char sStr2[4]; 5}stTest1 ; 6 7typedef struct{ 8 stTest1 sTest1; 9 10 int iVal1 ; 11 int iVal2 ; 12}stTest2 ;

と定義するのが一般的でしょうか。

strTest2 の sStr0、sStr1、sStr2 への参照は 1つネストが入りますが。

全体の代入は = 一発でできるようになります。

投稿2018/08/29 08:14

showkit

総合スコア1638

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

showkit

2018/08/29 08:20

あ、見誤っていました。それぞれの sStr0、sStr1、sStr2 は微妙にサイズが違っていたのですね。早とちり申し訳ありません。この 解凍は無視してください。
watan

2018/08/30 00:53

いえ、サイズ違いは私の記載ミスでした。申し訳ありません。 回答とても助かりました。こちらの方法で実装したいと思います。
guest

0

一つずつ入れる以外の万能な方法はないです。コンパイラ次第では、要素の並びが変わったりパディングが自動で入るためです。

投稿2018/08/29 08:23

HogeAnimalLover

総合スコア4830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2018/08/29 08:36

パディングがあるのは間違いないですが、メンバの順序については、規格上は「宣言された順に増加するアドレスをもつ」「メンバの記憶域は,並べられた順に割り付ける」ということになっているので、コンパイラの都合で並べ替えを行うのは、規格外の動作ということにはなります。
HogeAnimalLover

2018/08/29 09:00

おっと。それは失礼しました。ありがとうございます。
watan

2018/08/29 23:39

回答ありがとうございました。 やはりひとつずつ入れていくのが良いのですね。 これは仮に同じ型の構造体へコピーする場合でも同じとなりますか?
HogeAnimalLover

2018/08/30 00:04

同じ型ならば普通に代入すればいいですよ。つまり、=演算子だけで充分です。複数まとめるならばmemcpy系の関数が妥当です。
watan

2018/08/30 00:55

ありがとうございました。勉強になります。助かりました。
guest

0

ベストアンサー

元の構造体にメンバを追加したものが先の構造体である、のであれば、ポインタを利用して memcpy すれば(元が先より小さい場合には)できることはできるのですが……
書かれているコードを見ると、メンバ sStr0 が、char[9] と char[4] という形で、異なっています。

これだとメモリコピーで済ませることができないので、愚直に一項目ずつコピーするしかありません。

投稿2018/08/29 08:17

tacsheaven

総合スコア13703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

watan

2018/08/29 23:41

回答ありがとうございました。sStr0は私の記載ミスでした(訂正いたしました)。すみません。 同じ場合はメモリコピーで対応できるということなのですね。ありがとうございました。
tacsheaven

2018/08/30 00:10

必ずしもそうとは限らないのが面倒な話なのですが……環境によって構造体のサイズがパディングされる場合、元の構造体のサイズが 12 ではなく 16 になってたりする場合があります。(後ろ4byteは使わない空き領域だが確保される) そうなると、先の構造体では、「使われていない空き領域」が iVal1 とかぶります。結果的にメモリコピーしてしまうと、意図しない値が設定されることになります。 どういう動きをするかは「実装依存」になってしまうので、なんともいえないのです。
watan

2018/08/30 00:54

なるほど。とても理解できました。 やはり1項目ずつコピーしていくのが確実のようなので、その方法で対応してみたいと思います。 ありがとうございました!
guest

0

構造体を以下のように変更してはどうでしょうか。

C

1typedef struct{ 2 char sStr0[4]; 3 char sStr1[4]; 4 char sStr2[4]; 5}stTest1 ; 6 7typedef struct{ 8 stTest1 st; 9 int iVal1 ; 10 int iVal2 ; 11}stTest2 ;

アクセスするにはstTest2.st.sStr0といったように階層構造でアクセスします。
memcpy等で実現できるかと思われます。

投稿2018/08/29 08:16

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

watan

2018/08/30 00:52

そのような記載ができるのですね。勉強になりました。 アクセスの仕方まで教えていただきありがとうございます。こちらの定義の仕方を用いて実装してみようと思います。
guest

0

sStr0,sStr1,sStr2を項目一つずつする以外に構造体ごとコピーできる方法があれば教えてください。

正しくできると保証された方法はありません。そもそもstTest1stTest2で先頭のsStr0の長さも違っているので、両者はメモリ構造も異なります。

投稿2018/08/29 08:15

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

watan

2018/08/30 00:52

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

0

つmemcpy(kCopy[iLp], kFrom[iLp], sizeof(stTest1));

投稿2018/08/29 08:17

hichon

総合スコア5737

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hichon

2018/08/29 08:21

stTest1の「char sStr0[9];」は「char sStr0[4];」の間違いですよね
watan

2018/08/29 23:34

その通りです。間違いでした。 ご指摘ありがとうございました。 また回答ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問