
No.1ベストアンサー
- 回答日時:
いろいろありますが、一例として...
union xxx
{
unsigned char d[0x10000];
long long force_aligner;
};
のようにすれば、配列dを強制的にlong longと同じ境界調整を行うことができます。
典型的に使い方としては、
union yyy
{
uint8_t b[2];
uint16_t w;
};
のような感じで、16ビット整数としても、それを上下に分割した8ビット整数としても使えるような型を定義するのがあります。
ただし、バイトーオーダーが処理系に依存するので、濫用するのは関心できません。
同様に、ビットフィールドを組み合わせるやりかたもあります。これもビットオーダーが処理系に依存しますので要注意です。
回答ありがとうございます。
・1つ目について
境界調整(アラインメント)についての理解が完全ではないのであまり自信はありませんが、もし違っていたらご指摘願います;;
共用体のメンバにlong long型の(=どのデータ型にも適合できるような)アラインメント用ダミー変数を挿入することによって、必ず&d[0]が8の倍数アドレスに割り当てられる、ということでよろしいですかね。
こうすることで冗長(?)なメモリアクセスをなくせる・・・と、解釈しておりますが。
・2つ目について
No.2、No.3の方が言っておられるテクニックですね。
データを(例えば)上位と下位で分けて扱いたい場合に共同体を使うことでお手軽に扱える、と。
組み込みでよく見そうなunionの活用法ですね。
No.9
- 回答日時:
Wndows Mobileで以下のようなものがあります。
typedef union CEVALUNION {
short iVal;
USHORT uiVal;
long lVal;
ULONG ulVal;
FILETIME filetime;
LPWSTR lpwstr;
CEBLOB blob;
BOOL boolVal;
double dblVal;
} CEVALUNION;
typedef struct CEPROPVAL {
CEPROPID propid;
WORD wLenData;
WORD wFlags;
CEVALUNION val;
} CEPROPVAL;
データの受け渡しはstruct CEPROPVALで。
共用体valに入っているデータのタイプはpropidで区別。という具合です。
最近関わっているプロジェクトでは、組み込み系でメモリ容量に制限があって、各通信データごとの構造体を個別に持てないので、
共用体にして1つの大きく確保した領域(グローバル変数)を使い回しています。
# 勿論、途中で別のデータを入れたりしたら元のものは壊れるコトになりますが…。
# そうならないように制御しています。
No.8
- 回答日時:
個人的に固定長データを扱うときによく利用しています。
NUL終端しないのでマクロなり専用関数とセットですが。。。
union
{
char *stream;
struct
{
char field1[1];
char field2[5];
char field3[10];
} f;
} in_data;
としておいて、読み取り/書き込みは
fgets(in_data.stream, sizeof(in_data.f), fp) みたいな感じ
使うときは
printf("%.*s", sizeof(in_data.f.field2), in_data.f.field2);
まぁ、直接構造体を (char *)しちゃってもいいんですけどね
キャストはあまり好きじゃないんで。。。
あと、トリッキーですが上の応用で
文字列を連結できたり/可変長レコードを処理できますね
No.7
- 回答日時:
私自身は共用体を使うことはほとんどありませんが、
ネットワーク系のプログラムでIPヘッダの構造体に使用しているのを見たことがあります。
IPヘッダではそれぞれのデータが4ビットであったり32ビットであったりとデータのビット長がバラバラですが、
チェックサムを計算する際には同じビット長でアクセスできた方が都合が良いため、
通常のデータ参照用の変数と、チェックサムを計算するための固定長の配列の変数とを共用体にして、
それぞれの用途で使用していました。
No.6
- 回答日時:
> ・例外的な存在というのは上記でURLで言う「アラインメントに寛容なCPU」を指すものであって、アラインメントに厳格なCPUではご指摘の通りアラインメントが正しく行われていない場合の動作は未定義→エラー。
未定義というのはエラーになるかどうかもわかりません。
例えば、あるCPUでは、奇数番地にワードアクセスしようとすると、勝ってにアドレスの下位ビットを0に置き換えてしまったりします。つまり、期待していないアドレスへのアクセスになってしまいます。
これは、一見動作するように見えるので、深刻なバグにつながります。
> ・(私の使っているパソコンのCPUは寛容な方だったので)アラインメントに特に気を配らなくてもアクセスは行える→アクセスが遅くなるだけで済む。
> なので冗長なメモリアクセスと解釈したが、実際は他のCPUでは動かないことの方が多い。
8ビットCPUの場合は確実に動きます。
16ビットCPUになると動くもの、動かないものが出てきます。
32ビット以上の場合、8ビットや16ビットCPUの上位互換として発展してきたものを除けば、まともに動かないのが普通です。
No.5
- 回答日時:
#1 です。
> 共用体のメンバにlong long型の(=どのデータ型にも適合できるような)アラインメント用ダミー変数を挿入することによって、必ず&d[0]が8の倍数アドレスに割り当てられる、ということでよろしいですかね。
8の倍数かどうかは処理系によりますが、まあそういうことです。
> こうすることで冗長(?)なメモリアクセスをなくせる・・・と、解釈しておりますが。
こんなことをするのは、多くの場合、ハード的な制約からです。
ですので、冗長なメモリアクセスというよりは、こうしていなければ動かないことが多いといえます。
あるいは、mallocのようなメモリアロケータを自作する場合にもこういった手法を使うことがあります。
その場合、配列の要素へのアクセスは、unsigned char以外の型のポインタを介して行われることがあります。
境界調整が正しく行われていない場合の間接参照は未定義の動作ですので、CPU例外が発生したり期待しないアドレスにアクセスすることがあります(IA-32などはどちらかといえば例外的な存在です)。
ありがとうございます。
度々申し訳ないのですが、自分の解釈を以下に書いてみますので誤りなどがあればご指摘お願いします。
※ご指摘を理解するにあたって、http://www5d.biglobe.ne.jp/~noocyte/Programming/ … を参考にしました。
・例外的な存在というのは上記でURLで言う「アラインメントに寛容なCPU」を指すものであって、アラインメントに厳格なCPUではご指摘の通りアラインメントが正しく行われていない場合の動作は未定義→エラー。
・(私の使っているパソコンのCPUは寛容な方だったので)アラインメントに特に気を配らなくてもアクセスは行える→アクセスが遅くなるだけで済む。
なので冗長なメモリアクセスと解釈したが、実際は他のCPUでは動かないことの方が多い。
No.4
- 回答日時:
パケットを表す構造体とかで、
struct A{
....
};
struct B{
....
};
struct C{
....
};
enum TYPE{TYPE_A,TYPE_B,TYPE_C};
struct packet
{
TYPE type;
union DATA{
A a;
B b;
C c;
}data;
};
なんてのが時々ありますね。
ありがとうございます。
私はその表現は見たことがないのですが、パケットの種類が違っても同じデータ構造で扱える、という感じの使い方ですね。
送受信の対象となるデータ構造を1つにする→プログラムが組みやすい(?)・・・という感じでしょうか。
No.3
- 回答日時:
C のバイブル(K&R)の利用例では迫力がありませんが,マイクロプロセッサのシミュレーションでレジスタペア(※)の表現に重宝だと思いました.
※ i8086 の AX=(AH, AL) は AH, AL を独立に使うことも AX として使うこともできます.最近の CPU のアーキテクチャは知りませんが,同様ではないでしょうか(無責任推測).
回答ありがとうございます。
そういえば以前私は組み込みをやっていたんですが、
レジスタ定義ファイルに共同体がバリバリ使われていました。レジスタそのものと、中身のビットを共同体で定義することでどちらでも扱えますよ、と。
初めて見た時には「うまいなぁ…」と思いました。似たような例として思い出したので書かせてもらいました(笑)
No.2
- 回答日時:
苗字はなんていうんですか? 東京です
下のお名前は? ばな奈です
貴方のフルネームは? 東京ばな奈です
こんなとき貴方は”苗字”、”下の名前”、”氏名”って持ちますか?
それとも苗字と下の名前を合わせたのが氏名だって考えますか?
こんな例っていっぱいありますよね。
住所だって、その中には都道府県も含んでるし、市区町村も含んでます。
住所と都道府県、市区町村を別々に持ちますか?
住所が”東京都千代田区丸の内XXX”ってなってるのに都道府県が”大阪”だったら「どうすんねん!」です。
いちいち2回も3回も書くの面倒だし、書き間違えたら困りますからね。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(コンピューター・テクノロジー) USBメモリのアクセスの遅い部分を避けて利用する方法 5 2022/10/18 13:32
- デスクトップパソコン intel hdグラフィックス3000 4 2022/10/03 14:14
- C言語・C++・C# C言語について コマンドラインで >変数 12.00 (char型) と、小数点付きの値を共用体に渡 1 2022/04/22 16:56
- C言語・C++・C# C言語 共用体について コマンドライン引数で値を2つ入力したときに、argv[2]の値をUNI u1 4 2022/04/25 20:34
- ドライブ・ストレージ HDDの書き込み回数と寿命について 7 2022/06/04 11:55
- 憲法・法令通則 公共施設の利用と集会の自由との関係に関する説明のうち、適当でないものを1つ選びなさい。 ① 集会の自 1 2022/11/27 09:06
- 財務・会計・経理 一括償却資産のメリットについて 2 2022/10/15 21:58
- 統計学 主成分分析について 1 2022/06/14 14:53
- 法学 共用部分たる旨の登記がされている区分建物の共有持分の登記移転登記の申請は登記することはできない。 1 2023/01/04 02:11
- 戸籍・住民票・身分証明書 マイナンバーカードの更新について教えてくださいな マイナンバーカード更新の時期が来たので携帯で済ませ 2 2023/07/31 01:47
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
CStringからchar*への型変換に...
-
char*を初期化したいのですが
-
fgetc( )の戻り値はなぜ整数??
-
C言語のintとcharの違いってな...
-
char型にint型の数値を代入する。
-
C言語にて構造体のメンバがNULL...
-
csvファイルをfscanfで読み込む...
-
Micom Car Rally に向けて製作...
-
簡易版smtpクライアント(メール...
-
char 文字列型 の表現範囲が-12...
-
char AA[]{"全角文字"};から"全...
-
エクセルのMID関数は、C言語では?
-
Cの関数の引数のconst *charに...
-
C++17で、unsigned char * 配列...
-
警告
-
wsprintf( ポインタ , "%d" , "...
-
C言語のプログラムについてです
-
構造体のメンバーの静的なサイ...
-
ポインタとcharについて
-
文字型配列に格納した空白の切捨て
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CStringからchar*への型変換に...
-
char*を初期化したいのですが
-
C言語にて構造体のメンバがNULL...
-
C言語のintとcharの違いってな...
-
DWORDとcharの変換
-
C++17で、unsigned char * 配列...
-
char 文字列型 の表現範囲が-12...
-
new charとnew char[N]の違いは?
-
char型にint型の数値を代入する。
-
動的メモリの初期化方法について。
-
小数点入りの文字列をfloat型に...
-
文字型配列に格納した空白の切捨て
-
fstream型オブジェクトを関数の...
-
C++Builder 2009 テキスト...
-
文字列の途中から途中までを抽出
-
C言語の文字リテラル中の16進文...
-
エクセルのMID関数は、C言語では?
-
文字列のswap
-
void型へのポインタ
-
VC++ char[10]へのCString値の代入
おすすめ情報