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

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

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

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

Q&A

解決済

5回答

753閲覧

C言語の構造体でのポインタ参照

ParaParaDance

総合スコア56

C

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

0グッド

1クリップ

投稿2020/06/08 07:47

編集2020/06/08 08:04

下記コードのような構造体を作り、ポインタ増やしながら値を代入したいです。
色々試しましたが、うまく行きません。構造体メンバへのアドレス指定方法についてアドバイスをお願いします。

typedef struct { uint32_t a //Address offset: 0x00 uint8_t b //Address offset: 0x04 uint32_t c //Address offset: 0x05 }s_instance; s_instance *instance; void hoge(s_instance *hoge){ hoge offset 0x00番地に値を代入 hoge offset 0x04番地に値を代入 hoge offset 0x05番地に値を代入 }

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

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

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

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

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

maisumakun

2020/06/08 08:01

実際に試したコードも書いていただけますか?
YT0014

2020/06/08 08:05

提示された構造体のメンバーへの代入処理を行いたいのですか? それとも、dllの呼出しなどのため、任意のオフセット位置にメンバーを配置した構造体を作りたいということですか?
YT0014

2020/06/08 08:06

あと、uint32_t a と、unit8_t b は、型が逆ではないでしょうか?
ParaParaDance

2020/06/08 08:09 編集

ただ、構造体メンバーへ代入したいです。 uint32_t *pp; uint8_t xx = 0x04; pp = &hoge->a + xx; *pp = 100; こんな感じでエラーでなくなりましたが、これで問題ないですかね?
ParaParaDance

2020/06/08 08:11

YT0014>> メンバのデータ型がバラバラになっているデータベースのようなものを作っています。 ですから、逆ではありません。
YT0014

2020/06/08 08:14

型ではなく、オフセットが誤っていたんですね、納得しました。
maisumakun

2020/06/08 08:14

なぜ、ポインタをオフセット演算させる必要があるのでしょうか。 その必要がないなら、構造体全体のポインタからメンバ参照を行うほうが適切かと思います。
ParaParaDance

2020/06/08 08:19

そうした書き方だとメンバが多すぎて、switch文が長くなるからです。 ポインタ指定ですと、入ってくるデータにoffset番地属性だけ指定しておけば、アクセスできるからです。
YT0014

2020/06/08 08:33

動かなくても良いので、そのswitch文をご提示いただけないでしょうか? 私には、ParaParaDanceさんのやりたいことが理解できておりません。
ParaParaDance

2020/06/08 08:48

#typedef struct{ uint8_t a, uint32_t b, uint32_t c ・・・・・・100個。 }hoge_def; void switch(hoge_def *hoge, uint32_t data){ switch(data){ case 0: hoge->a = 100; break; case 1: hoge->b = 200; break; case 2: hoge->c = 300; break; .........100個} }  ポインタを使わないとcaseを100 個作る必要があります。  これをポインタ参照にし、data xは &hoge->a + 0x??;のようにしたいわけです。
guest

回答5

0

正直,質問者がやりたいこと(およびその利点)がまるで理解できていませんが,
構造体のメンバの並びを調整して,型毎に配列にでもしたら楽になるのではないかと想像します.

typedef struct { uint32_t U32[100]; uint8_t U8[50]; }

「uint32_t型の要素の何個目」とかでアクセスできるので,

switch文

で書くにしても,せいぜい型の種類の個数分の分岐で済むんじゃないか? と.

投稿2020/06/08 09:40

fana

総合スコア11996

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

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

0

「ポインタ増やしながら」の意味がわかりませんが
代入したいだけならば

c

1void hoge(s_instance *hoge){ 2 hoge->a = A; 3 hoge->b = B; 4 hoge->c = C; 5} 6void hoge2(s_instance *hoge){ 7 (*hoge).a = A; 8 (*hoge).b = B; 9 (*hoge).c = C; 10}

がC言語的に正しい方法です。

無理やりキャストを行って

c

1#include <stddef.h> 2#include <stdint.h> 3void hoge3(s_instance *hoge){ 4 uintptr_t p = hoge; 5 *(uint32_t*)(p+offsetof(s_instance, a)) = A; 6 *(uint8_t* )(p+offsetof(s_instance, b)) = B; 7 *(uint32_t*)(p+offsetof(s_instance, c)) = C; 8} 9void hoge4(s_instance *hoge){ 10 char* p = hoge; 11 *(uint32_t*)(p+offsetof(s_instance, a)) = A; 12 *(uint8_t* )(p+offsetof(s_instance, b)) = B; 13 *(uint32_t*)(p+offsetof(s_instance, c)) = C; 14}

みたいな事もできなくはありませんが…無駄に面倒なのでやめた方がよいです。

投稿2020/06/08 08:27

asm

総合スコア15149

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

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

0

構造体は指定しないと1バイト単位できっちり詰まりません。

uint8_t b

の部分は、1バイト+パティング3バイトになりそうな気がします。4バイト単位(処理系にもよりますが)のメモリ境界に配置しないとアクセス効率が落ちるため、コンパイラがパティングをします。1バイト単位で詰めるなら、こんな感じになると思います。

C++

1#pragma pack(1) //packを1バイト単位にする 2typedef struct 3{ 4 uint32_t a //Address offset: 0x00 5 uint8_t b //Address offset: 0x04 6 uint32_t c //Address offset: 0x05 7}s_instance; 8#pragma pack() //packを戻す

pragma pack
(Microsoftの機械翻訳怪しいので英語にして読んだほうがいいかも)

投稿2020/06/08 13:17

編集2020/06/08 13:35
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

ベストアンサー

構造体メンバーへ代入したいだけならば

hoge->a = 100;
hoge->b = 100;
hoge->c = 100;

なお、オフセットに関しては、質問に記載された通りになっていない可能性があるのはご承知ください。

使い方の詳細は「アロー演算子」辺りを調べてください。

switchをいくつも書き連ねたくないとのことなので、こんな書き方はいかがでしょうか?

C

1typedef struct 2{ 3 uint32_t a; 4 uint8_t b; 5 uint32_t c; 6} s_instance; 7 8typedef struct 9{ 10 uint32_t data; 11 void (*setter)(s_instance* hoge, uint32 value); 12} DateSetter; 13 14void setterToA(s_instance* hoge, uint32 value) 15{ 16 hoge->a = value; 17} 18 19void setterToB(s_instance* hoge, uint32 value) 20{ 21 hoge->b = (uint8_t)value; 22} 23 24void setterToC(s_instance* hoge, uint32 value) 25{ 26 hoge->c = value; 27} 28 29DateSetter[] dataSetterArray = 30{ 31 { 0, setterToA }, 32 { 1, setterToB }, 33 { 2, setterToC }, 34 { 3, setterToA }, 35 { 4, setterToA }, 36 { 5, setterToA }, 37 { 6, setterToB }, 38 { 7, setterToB }, 39 { 8, setterToC }, 40 { -1, NULL } // 終端マーク 41}; 42 43void hoge(s_instance *hoge, uint32_t data){ 44 for (int i = 0; dataSetterArray[i].setter != NULL; i++) { 45 if (dataSetterArray[i].data == data ) { 46 *(dataSetterArray[i].setter)(hoge, data); 47 break; 48 } 49 } 50}

申し訳ありませんが、環境がないので、未検証です。
関数ポインタからの呼出しが誤っていたら申し訳ございません。

投稿2020/06/08 08:13

編集2020/06/08 09:22
YT0014

総合スコア1750

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

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

0

uint32_t a //Address offset: 0x00 uint8_t b //Address offset: 0x01

この時点でおかしいです。baの領域に食い込んでしまっているので、このような配置にはなりません。

投稿2020/06/08 07:51

maisumakun

総合スコア146018

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

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

ParaParaDance

2020/06/08 07:55

構造体なのにどうしてbがaへ食い込むのですか? 積み上げでbufferが配置されるのではないですか?
maisumakun

2020/06/08 08:00

> 積み上げでbufferが配置されるのではないですか? そうです。だから、bのオフセットは0x01にはならず、もっと後になります。
ParaParaDance

2020/06/08 08:03

あ、すみません。offset番地の記入を間違えました。正しくは以下の通りです。修正します。 uint32_t a //Address offset: 0x00 uint8_t b //Address offset: 0x04 uint32_t c //Address offset: 0x05
maisumakun

2020/06/08 08:08

> 正しくは以下の通りです。 とも限りません。アラインメントの関係上、cが0x05に来ない可能性も高いです。
ParaParaDance

2020/06/08 08:13 編集

Windowsではなく、ARMの直叩きなのに連続アライメントにならない場合もあるでしょうか?
maisumakun

2020/06/08 08:18 編集

古いARMはアライメントを守らないとまともに処理できませんし、それ以降でも境界がずれたデータをハンドリングさせるには設定が必要です。 x86のほうが、境界ズレには寛容です。
maisumakun

2020/06/08 08:25 編集

> ポインタ指定ですと、入ってくるデータにoffset番地属性だけ指定しておけば、アクセスできるからです。 でしたら、自分でオフセットを数えずに、offsetofのようなマクロを使いましょう。
ParaParaDance

2020/06/08 08:41

こういうマクロもあったのですね。有難うございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問