teratail header banner
teratail header banner
質問するログイン新規登録

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

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

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

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

4回答

5399閲覧

memcpyを使わずに構造体から配列にコピーしたい

hachimitu

総合スコア36

C

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2019/06/29 23:51

0

0

#実現したいこと
これまで構造体から配列にコピーするときにmemcpyを使用していました。しかしmemcpyは処理時間がかかるということなのでmemcpyを使用せずにコピーする方法を模索しています。

#試したコード
分かっていましたがエラーでした。。。。
uint8_t dumy_data[64] = {0};

copy_to_array_little_end(dumy_data,&Mst_to_pc_data_frame_struct,MST_TO_PC_DATA_FRAME_handle_typedef_size);

void copy_to_array_little_end(uint8_t *buffer ,MST_TO_PC_DATA_FRAME_handle_typedef *mst_to_pc_data_frame_struct, uint8_t size)
{
uint8_t tmp_i;

for(tmp_i = 0;tmp_i < size; tmp_i++)
{
buffer = mst_to_pc_data_frame_struct; /構造体のアドレスと配列のアドレスをインクリメントさせながらコピーしたかった/
buffer++;
mst_to_pc_data_frame_struct++;
}
}

#質問
memcpyを使わずに構造体から配列にコピーする方法はありますでしょうか。お手数をおかけしますが宜しくお願い致します。

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

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

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

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

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

guest

回答4

0

ベストアンサー

memcpyは処理時間がかかる

どこのどいつがそんなこと言った? その理由は?
memcpyは"最速コピー"と言っていいぞ?

※ コピーにはそれ相応の時間がかかるから
「コピーせずに済ませられるならそれに越したことはない」
ってニュアンスならわかる。

投稿2019/06/29 23:55

編集2019/06/30 00:02
episteme

総合スコア16612

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

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

hachimitu

2019/06/30 00:00

下記urlの方がいっていました。 http://tandyco.cocolog-nifty.com/blog/2012/09/c-20120908-memc.html すみません、理由まではわからないです。 サイトでもおっしゃてる様に、memcpyは処理時間がかかるというのは相対的に時間がかかると言っているみたいです。
hachimitu

2019/06/30 00:04

※ memcpyは"最速コピー"と言っていいぞ? ⇒そうなんですか!? ①と②で処理時間計測してみます。ありがとうございましたm(__)m ① data[0] = 0x12 data[1] = 0x34 sequence = data[0] << 8 | data[1]; ② memcpy(&sequence, data, 2);
episteme

2019/06/30 00:07

「ほんの数バイトのコピー」にmemcpyしたら時間かかるやろから素直に代入しろ。ならそうかもね。
hachimitu

2019/06/30 00:07

※ コピーにはそれ相応の時間がかかるから 「コピーせずに済ませられるならそれに越したことはない」 ってニュアンスならわかる。 ⇒なるほど、コピーしたいデータサイズにもよるかもしれませんね。 上の①とかなんかはコピーというより代入とビットシフトだけの処理だから、ブログの人は①の方が処理時間はやいって言ってるかもですね。
hachimitu

2019/06/30 00:11

ちなみに質問の Q/*構造体のアドレスと配列のアドレスをインクリメントさせながらコピーしたかった*/ ってできるんでしょうか。 もうmemcpyでよい気もしてきましたが。。。
episteme

2019/06/30 00:15

両者のポインタを uint8_t* にキャストしてloopでくるくる回せばできるけど、 それってmemcpyの中でやってることと同じ(かそれ以下)。
hachimitu

2019/06/30 00:17

"それってmemcpyの中でやってることと同じ(かそれ以下)。" ⇒そうですね。了解です。ありがとうございました。すっきりしました。
pepperleaf

2019/06/30 00:24

ん、以前見た memcpyのコード(32bit CPU)は、32bitでコピーしてた。前処理と後処理、何かと思ったら、端数に関する処理及び、場合分け。 従って数バイトだと、単純コピーより、遅い。(と言っても元々、僅かな時間) あと、CPUがブロック転送命令持ってるとそれ使ってる可能性もあります。
catsforepaw

2019/06/30 01:06

今時のコンパイラーは、最適化が有効ならmemcpyを関数呼び出しではなくCPU命令に展開しますから(しかもかなり賢い)、epistemeさんが回答したように「最速コピー」と考えて間違いありません。memcpyのパフォーマンスを超えるコピーロジックをCで組むのは、たぶん無理です。
pepperleaf

2019/06/30 01:15

catsforepawさん、レアケース(かつ、CPU依存)だと思いますが、 memcpyは、byteアドレスが渡されます。これが、32bit境界(or 64,,,)に一致するかの判断が自動で出来ないケースもあり、そんな場合は、可能です。
catsforepaw

2019/06/30 01:30

pepperleafさん > 32bit境界(or 64,,,)に一致するかの判断が自動で出来ないケースもあり、 意味がよく判りません。下位ビットをテストすれば自動で判断できると思うのですが……。もしそんなケースがあるのなら、自前でロジックを組む際も判断できないということになり、結局パフォーマンスを上げられませんよね。
pepperleaf

2019/06/30 01:46

まず、渡される引数が、複数の関数を経てくる場合、アライメントの一致は、形式的に分かりません。(設計者なら、32bit x n が分かる事もある) 下位ビットのテストですが、事前に分かっていれば、そもそもテストが不要です。(最初から、 32bit x n のコピーができる) あまり一般的ではないですが、少しでもって時に使いました。(回答に書いた件。アセンブラ出力見ながら)
asm

2019/06/30 02:21

何バイトコピーするかやコピー先・元アドレスがアライメントされている事がコンパイル時に決定している場合 かつ、使用するCPUが特定できる場合ならばmemcpyよりも高速なコピーはありえます。 が、逆に言えばそこまで考慮しないとmemcpyより高速なコピーはまずないでしょう。
catsforepaw

2019/06/30 02:55

つまり、「アラインメントが一致することが保証された前提のコードを書く」ということですね。まぁ、可能性はなくはないですが、だとしてもC標準のコードではたぶん無理です。memcpyはコンパイラー開発者が威信をかけて最適化しているはずなので(おそらく「*p1 = *p2」のコード展開と共通と思われ)、それを超えるパフォーマンスを出すにはよほどCPUを熟知した上でSIMD組み込み関数等の標準外の機能を駆使しないと。 ちなみに、VC++のmemcpyでは、SSEの128bitレジスターを使いつつ命令の同時実行も考慮したコードが出力されます。これを超えるパフォーマンスを出せといわれてすぐに書ける自信は、私にはありません。
pepperleaf

2019/06/30 08:16

> memcpyはコンパイラー開発者が威信をかけて最適化している というのも実はレアケース。メジャーなCPUならともかく、組込みあたりだと、結構、???です。ただ、標準関数使っておけば、大抵の場合、問題が少なく、互換性を悩む必要も少ない。 asmさん、言われる通りです。 一応、CPU変わっても動くように、が、頭痛かったです。(ただし、パフォーマンスは別)
guest

0

下記urlの方がいっていました。

ここで書かれていることを端的に書くと、

C

1int x,y; 2 3x = y; /* 速い */ 4memcpy(&x, &y, sizeof x); /* 遅い */ 5

そりゃそうです。

投稿2019/06/30 01:12

otn

総合スコア86341

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

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

pepperleaf

2019/06/30 01:23

確かに、、、数バイトのデータだと関数呼び出しコストがバカにならない。 > memcpy(&sequence, data, 2); なんか、昔、よく見た気がする。通信処理に多かったか? 無駄な事すると、思いつつも、うかつに触ってバグの元も困ると、放置してた気がする。
catsforepaw

2019/06/30 01:37

epistemeさんへのコメントで書きましたが、念のためVisual Studio 2019で試したところ、リリースビルドでは両者まったく同じコードが出力されました。
otn

2019/06/30 09:00

へえ。同一プロジェクト内で自前で同名の関数を定義していないことを検知した上でインライン展開するんですかね。
guest

0

ほとんど、解決になってるみたいですが、参考として、、
処理が遅いという事で、調べたら、バッファクリアで時間が掛かっている事が判明し、その高速化を試みて、その処理(メモリーコピー)を 2,3割減らしたが、全体としては、数% でほとんど効果無し。 何処で使われているか、調べたら、そもそもその関数そのものが不要だった事が判明。なんて事もありました。(結果、体感速度で向上)
処理が遅いと言う場合、それがそもそも必要かどうか検討する必要もあります。

投稿2019/06/30 00:35

pepperleaf

総合スコア6385

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

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

0

こんにちは。

「memcpyは処理時間がかかる」なんてことはありません。もしかして「コピーは処理時間がかかる」といわれたということはないでしょうか? 要するにコピーしなくてもできるってことでは?
今どきは推奨されないテクニックですが、C言語では使わざる得ないメジャーなテクニックがあります。

C

1uint8_t* dumy_data = (uint8_t*)&Mst_to_pc_data_frame_struct; 2for (int i=0; i < MST_TO_PC_DATA_FRAME_handle_typedef_size; ++i) 3 printf("%d\n", dummy_data[i]);

(コンパイルしていないので、エラーがでたらごめんなさい。)

投稿2019/06/30 00:08

Chironian

総合スコア23274

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

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

hachimitu

2019/06/30 00:14

回答ありがとうございます。 "もしかして「コピーは処理時間がかかる」といわれたということはないでしょうか?" ⇒はい、僕が参照したurlはそういってました。epistemeさんとも同じような話になりました。 詰まるところ、コピーしたいデータサイズによるだろうと。。。 コードありがとうございます。試してみます!
hachimitu

2019/06/30 00:42

#C void copy_to_array_little_end(uint8_t *buffer ,MST_TO_PC_DATA_FRAME_handle_typedef *mst_to_pc_data_frame_struct, uint8_t size) { buffer = (uint8_t* )&mst_to_pc_data_frame_struct; } コピーできなかった。。。。
episteme

2019/06/30 00:57

↑その& 要らなくね?
hachimitu

2019/06/30 01:16 編集

"その& 要らなくね?" ⇒buffer = (uint8_t* )mst_to_pc_data_frame_struct;で  コピーできました!!ありがとうございます。 間違っていたら指摘していただきたいのですが、この場合 1 "buffer"はuint8_t型ポインタでアドレスを格納できる。 2 (uint8_t* )mst_to_pc_data_frame_structはuint8_t型のポインタで mst_to_pc_data_frame_struct 全体のアドレス(先頭アドレスから構造体末尾のアドレスまで)が入っている 3 構造体のアドレスをbufferにセットすることでコピーできた
episteme

2019/06/30 01:57

いぃんぢゃね? で、これだとmemcpyより速いって?
hachimitu

2019/06/30 02:53

"いぃんぢゃね? で、これだとmemcpyより速いって?" ⇒違います。ポインタの使い方を確認したかっただけです。 個人的には、memcpyの処理速度うんぬんではなく、"memcpyを使わずにコピーできるの"ってところが知りたかったので。 いろいろと教えてくださり助かりました!ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問