簡體   English   中英

為什么將結構地址轉換為int指針,解除引用,並將其用作語句中的LVALUE會使我的微控制器崩潰?

[英]Why does casting a struct address to an int pointer, dereferencing, and using that as the LVALUE in a statement crash my microcontroller?

以下代碼在運行時崩潰了我的微處理器。

struct dummytype dummy;
struct crummytype crummy;
*(unsigned int*)&dummy = *(unsigned int*)&crummy;

假設兩個結構都是相同的大小,這個代碼是否有一些無效的C? 它的有效性是否取決於任何特定的?

這僅在兩個結構都具有unsigned int作為第一個成員時才有效。

C99§6.7.2.1/ 13

在結構對象中,非位字段成員和位字段所在的單元具有按聲明順序增加的地址。 指向適當轉換的結構對象的指針指向其初始成員(或者如果該成員是位字段,則指向它所在的單元),反之亦然。 結構對象中可能存在未命名的填充,但不是在其開頭。

簡單地說,給定一個結構對象的地址,您可以將該地址轉換為指向第一個成員類型的指針:

struct A
{
    unsigned int n;
    char junk[5];
};

struct A a;
unsigned int *p = (unsigned int *)&a;  // OK. pointer is proper for first member type
unsigned long*x = (unsigned long *)&a; // BAD

簡而言之,如果兩個結構類型的第一個成員都具有unsigned int ,那么您的代碼才是合法的。 其他任何東西都是未定義的行為( void *不能承受,但因為它是不可解除引用的,所以這里真的不適用)。 每個結構類型“足夠大”以容納unsigned int是不夠的。 他們的第一個成員實際上必須unsigned int

即使兩個結構具有相同的大小,重疊行為也是不確定的。

如果結構是這樣的,上面的陳述將給出你正在尋找的結果。

struct dummytype
{
int a;
};
struct crummytype
{
int b;
};    

如果結構是這樣的,你不能說結果會是什么。

struct dummytype
{
char name[20];
int a;
};
struct crummytype
{
char name1[20];
int b;
};

通過int的對齊要求和別名規則(通過與對象的有效類型不同的類型的左值訪問對象),它是無效的C.

C99標准草案(附件J):

J.2未定義的行為

在以下情況下,行為未定義:

[...]將對象分配給不完全重疊的對象或具有不兼容類型的完全重疊的對象(6.5.16.1)。

然后,關於兼容類型:

6.2.7兼容型和復合型

如果類型相同,則兩種類型具有兼容類型。 用於確定兩種類型是否兼容的附加規則在6.7.2中描述了類型說明符,在6.7.3中描述了類型限定符,在6.7.5中描述了聲明符。 此外,如果它們的標記和成員滿足以下要求,則在單獨的轉換單元中聲明的兩個結構,聯合或枚舉類型是兼容的:如果使用標記聲明一個,則另一個應使用相同的標記聲明。 如果兩者都是完整類型,則以下附加要求適用:其成員之間應存在一對一的對應關系,使得每對相應成員都聲明為具有兼容類型,並且如果相應對的一個成員是使用名稱聲明,另一個成員使用相同的名稱聲明。 對於兩個結構,相應的成員應按相同的順序聲明。 對於兩個結構或聯合,相應的位域應具有相同的寬度。 對於兩個枚舉,相應的成員應具有相同的值。

使兩個結構體具有相同的大小並不足以使它們成為兼容類型,因此行為是不確定的。

編輯:為了完整起見,我將@PascalCuoq引用的摘錄添加到此帖子中的另一個答案的注釋中,這也是相關的:

6.5表達式

[...]

7

對象的存儲值只能由具有以下類型之一的左值表達式訪問:

  • 與對象的有效類型兼容的類型,
  • 與對象的有效類型兼容的類型的限定版本,
  • 與對象的有效類型對應的有符號或無符號類型的類型,
  • 與有效類型的對象的限定版本對應的有符號或無符號類型的類型,
  • 聚合或聯合類型,包括其成員中的上述類型之一(包括遞歸地,子聚合或包含聯合的成員),或者
  • 一個字符類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM