3

エラーが発生します

 error: aggregate value used where an integer was expected

このコードのコンパイルについて:

#include <stdio.h>
typedef unsigned long U32; 
typedef struct hello_s
{
  U32   a:8;
  U32   b:24;
}hello_t;

int main()
{
  hello_t str;
  U32 var;

  str.a = 0xAA;
  str.b = 0xAAA;
  var = (U32)str;
  printf("var : %lX\n", var);
  return 0;
}

誰かがエラーの意味と私が間違っていることを説明できますか?

編集:私はこれが愚かなことであることを理解しています。私が知りたかったのは、なぜコンパイラーがこれについて泣いているのかということでした。最初の32ビットを整数に割り当てることができないのはなぜですか。

4

4 に答える 4

5
var = (U32)str;

strは構造体型のオブジェクトであり、構造体オブジェクトを算術型のオブジェクトに変換できないためです。C では、この種の変換を実行できません。

構造体オブジェクトに整数としてアクセスしたい場合は、構造体とU32.

共通構造var = *(U32 *) str;は、C では未定義の動作であることに注意してください。エイリアシングとアラインメントの規則に違反しています。

于 2012-09-18T19:58:27.627 に答える
3

ええと、言語標準に反していると仮定して、C99仕様を間違えるべきではないと思います。

この規格では、変換の結果が異なるマシン/アーキテクチャ間で移植できない可能性があるとのみ述べられています。

特定のアーキテクチャで動作するようにプログラムをコーディングしている限り、問題はありません。

たとえば、オブジェクト(つまり、キー)を一意に識別するデータ構造DataStr_tの選択的なメンバーをグループ化し、別の構造体、たとえばDataStrKey_tにパックします。sizeof(DataStrKey_t)がsizeof(uint64)と等しいことを確認し、すべての実用的な目的で、扱いやすいのでuint64として使用します。

また、以下の操作も頻繁に行います。

memcmp(&var_uint64, &var_DataStructKey, sizeof(uint64));

マシンのキーを使用してオブジェクトの読み取りアクセスまたは書き込みアクセスを行う場合、変換の結果の値は予測可能であり、ビット単位の配置で一貫しています。「このデータのみ」を別のマシン(実際にはデータを書き込まなかった)に移動して読み取ろうとすると、問題が発生する可能性があります。

説明を増やしてコンパイルを成功させるために、プログラムを少し変更しました。ここでは、LINE_AとLINE_Bが同じマシンで実行されている限り、結果は常に予測可能です。ただし、(var_uint64、var_DataStructKey)をファイルに書き込んで別のマシンから読み取った場合、それらの入力された値に対してLINE_Bを実行すると、比較が失敗する可能性があります。

#include <stdio.h>
#include <string.h>

typedef unsigned long U32;
typedef struct hello_s
{
  U32   a:8;
  U32   b:24;
}hello_t;

int main()
{
  hello_t str;
  U32 var;

  str.a = 0xAA;
  str.b = 0xAAA;
  var = *(U32 *)(&str); //LINE_A

  if(0 == memcmp(&var, &str, sizeof(U32))) //LINE_B
      printf("var : %lu\n", var);

  return 0;
}

私の答えは遅すぎると思いますが、説明しようとしました。

于 2013-03-18T19:31:13.353 に答える
2

そして、そのキャストが正確に何をもたらすと思いますか? そのアドレスをintへのポインターにキャストして逆参照することはいつでもできます...しかし、安全にそうできると確信していますか(いいえ、できません)?構造体メンバーのアライメントはいつかあなたを悩ませますか (答えは「おそらく、はい、場合による」です)?

また、C99 標準から:

C99 §6.7.2.1、パラグラフ 10: 「ユニット内のビット フィールドの割り当て順序 (上位から下位、または下位から上位) は実装定義です。」

于 2012-09-18T20:00:58.700 に答える
1

それは必ずしも愚かなことではありません。私の場合、ネットワーク接続を介して送信する必要がある構造体があります。データは SPI バスを介してバイト形式で送信する必要があるため、構造体には一度に 1 バイトずつアクセスする必要があります。この定義を使用して、各バイトにアクセスしました。これを正しく行うには、プラットフォームのバイト順序に注意する必要があります。また、構造体が__PACKEDであることを確認する必要があります( C/C++: Force Bit Field Order and Alignmentも参照)。これにより、コンパイラはパディング ブロックまたはアライメント ブロックを挿入しません。これは、ビット メンバーのいずれかがバイト境界を越えた場合にも機能しません (少なくとも、Microchip XC16 コンパイラでは機能しません)。

typedef unsigned char byte;
#define STRUCT_LB(x) ((byte *)(&x))[0]
#define STRUCT_HB(x) ((byte *)(&x))[1]

これを行うより良い方法は、構造体をビットフィールドとバイト配列の結合として次のように定義することです。

typedef unsigned char byte;
typedef struct {
    union {
        struct __PACKED {
            byte array[2];
        } bytes;

        struct __PACKED {
            byte b0: 1;
            byte b1: 1;
            byte b2: 1;
            byte b3: 1;
            byte b4: 1;
            byte other: 3;
            byte more: 6;
            byte stuff: 2;
        } fields;
    };
} MyData;
于 2014-01-10T14:22:41.470 に答える