[英]Cast between struct pointer in C
請考慮以下代碼。
typedef struct{
int field_1;
int field_2;
int field_3;
int field_4;
uint8_t* data;
uint32_t data_size;
} my_struct;
void ext_function(inalterable_my_struct* ims, ...);
我想允許ext_function
(由第三方編寫)僅修改my_struct
field_3
和field_4
。 所以我做了以下事情:
typedef struct{
const int field_1;
const int field_2;
int field_3;
int field_4;
const uint8_t* data;
const uint32_t data_size;
} inalterable_my_struct;
void ext_function(inalterable_my_struct* ims, ...);
在調用ext_function
之前在my_struct
和inalterable_my_struct
之間轉換指針是否安全(如下所示)?
void call_ext_function(my_struct* ms){
inalterable_my_struct* ims = (inalterable_my_struct*)ms;
ext_function(ims, ...);
}
我不認為這是個好主意。
被調用的函數總是可以拋棄任何const
:ness,並在需要時修改數據。
如果您可以控制調用點,最好創建一個副本並使用指向該副本的指針調用該函數,然后復制您關注的兩個字段:
void call_ext_function(my_struct* ms)
{
my_struct tmp = *ms;
ext_function(&tmp, ...);
ms->field_3 = tmp.field_3;
ms->field_4 = tmp.field_4;
}
更清潔,除非你每秒數千次這樣做,否則性能損失應該很小。
如果函數觸及它,你可能也必須偽造基於指針的數據。
根據C99標准,即使兩個struct
的聲明相同,它們也不會具有兼容類型。 從6.7.7.5節:
例2聲明后
typedef struct s1 { int x; } t1, *tp1;
typedef struct s2 { int x; } t2, *tp2;
類型
t1
和tp1
指向的類型是兼容的。 類型t1
也與struct s1
類型兼容,但與struct s2
,t2
類型(tp2
或int
指向的類型)不兼容。
此外,具有不同限定符的兩種類型不被視為兼容:
要使兩種合格類型兼容,兩者都應具有相同類型的兼容類型; 說明符或限定符列表中類型限定符的順序不會影響指定的類型。
更簡潔的方法是完全隱藏你的struct
,用一個不起眼的句柄( void*
之上的typedef
替換它,並提供操作struct
元素的struct
。 通過這種方式,您可以完全控制結構的struct
:您可以隨意重命名其字段,根據需要隨意更改布局,更改字段的基礎類型,以及執行其他操作通常避免在客戶端知道struct
的內部布局時。
我不認為這是一個好主意,因為很難跟蹤結構是否已被轉換(特別是如果代碼很大)。 同時將其轉換為const並不能保證以后不會將其強制轉換non-const structure
。
放松提供的解決方案非常好。 另一種(也是更明顯的)解決方案是將結構分成兩個較小的部分。
typedef struct{
const int field_1;
const int field_2;
const uint8_t* data;
const uint32_t data_size;
} inalterable_my_struct;
typedef struct{
int field_3;
int field_4;
} my_struct;
void ext_function(const inalterable_my_struct* const ims, my_struct* ms ...);
我在上面的調用中使指針也保持不變,但這不是必需的。
它可能適用於大多數編譯器,即使標准沒有說明任何內容。 如果你真的需要,你甚至可以用聯盟做一些更便攜的東西。 除了它不會改變任何東西。
這就是為什么它不會改變任何東西:
$ cat foo.c
struct foo {
const int a;
int b;
};
void
foo(struct foo *foo)
{
foo->a = 1;
}
$ cc -c foo.c
foo.c: In function ‘foo’:
foo.c:9: error: assignment of read-only member ‘a’
$ cc -Dconst= -c foo.c
$
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.