2012-09-18 23 views
2

我收到錯誤錯誤而鑄字結構爲整數

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位分配給整數。

+3

嗯,這是有原因的錯誤...的原因是它沒有意義。想象一下,有人試圖將電話簿轉換爲整數... – 2012-09-18 20:00:54

+2

C語言本質上是非常原始的。因此,某些事情不被支持或允許。 C甚至不試圖在幕後爲你工作。沒有背後。從技術上講,C有多簡單?它幾乎與彙編語言或機器代碼一樣簡單。出於這個原因,你不能直接支持動態數組,任意的數字精度,很容易將事物彼此轉換(例如,從字符串到/從字符串),還有更多的東西。在你的程序或它使用的庫中必須有代碼來完成這項工作。 –

+2

爲什麼downvotes?我發現這個問題很有幫助,因爲我的情況相同。並且user529758不被要求 - 鑄造總是將蘋果轉換成橙子。 – Vorac

回答

5
var = (U32)str; 

因爲str是結構類型的對象,所以不能將結構對象轉換爲算術類型的對象。 C不會讓你執行這種轉換。

如果要以整數形式訪問結構對象,可以創建結構的並集和U32

請注意,常見構造var = *(U32 *) str;在C中是未定義的行爲。它違反了混疊和對齊規則。

+1

您可否詳細說明一下。爲什麼不能做到這一點。該結構僅使用32位內存。 – Pratt

+0

@普拉特你不可以,因爲它很難或什麼,你不能,因爲它是不允許的語言標準。 –

2

你期待什麼樣的結果?你總是可以將它的地址轉換爲指向int的指針並將其解引用......但是你確定你可以安全地這樣做(不,你不能)?結構成員對齊是否會在某天遇到你(答案是「可能,是的,它取決於」)?

此外,從C99 styandard:

C99§6.7.2.1,第10段:「位字段的分配單位(高位到低位或低階內的順序到高階)是實現定義的。「

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; 
} 

我想我的回答爲時已晚,但試圖解釋。

+0

這正是我一直在尋找的......關於如何使用這些數據的一個很好的解釋。我使用一個聚合值結構作爲標誌進行處理。我有很多標記要處理。迭代每一個都會產生很多開銷。最好將它們分成8組,並首先檢查其中一個是否改變。通過這種方式,我可以先用16比較檢查我的120標誌,然後再檢查單個標誌。正如我寫的,我不關心手術的結果。它的價值不等於零。 – andyinno

0

這並不總是一件愚蠢的事情。在我的情況下,我有一個結構,我需要通過網絡連接發送。數據必須以字節形式通過SPI總線發送,因此一次只能訪問一個字節的結構。我用這個定義來訪問每個字節。您必須瞭解您的平臺的字節順序才能正確執行此操作。此外,您必須確保結構爲__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;