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, ...);
我想允许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, ...);,c,casting,C,Casting,我想允许ext\u function(由第三方编写)只修改我的结构中的字段3和字段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
ext\u function
(由第三方编写)只修改我的结构中的字段3
和字段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\u函数
之前,在my\u struct
和inalterable\u my\u struct
之间强制转换指针是否安全(如下所示)
我认为这不是个好主意
被调用的函数始终可以丢弃任何常量
: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;
}
要干净得多,除非每秒执行数千次,否则性能损失应该很小
如果函数接触到指针数据,您可能也必须伪造它。它可能会在大多数编译器上工作,即使标准没有对它做任何说明。如果你真的需要的话,你甚至可以通过工会做一些更方便的事情。除非它不会改变任何事情
这就是为什么它不会改变任何事情:
$ 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
$
根据C99标准,两个struct
s即使声明相同,也不会有兼容的类型。根据第6.7.7.5节:
示例2在声明之后
类型t1
与tp1
指向的类型兼容。类型t1
也与类型struct s1
兼容,但与类型struct s2
、t2
、由tp2
或int
指向的类型不兼容
此外,具有不同限定符的两种类型被视为不兼容:
对于要兼容的两种合格类型,两者应具有相同的合格版本
兼容类型的;类型限定符在说明符或限定符列表中的顺序
不影响指定的类型
一种更干净的方法是将结构
全部隐藏起来,用一个模糊的句柄(位于void*
之上的typedef
替换它,并提供操作结构
元素的函数。通过这种方式,您可以完全控制结构的结构:您可以随意重命名其字段,尽可能频繁地更改布局,更改字段的基本类型,当客户知道结构的内部布局时,您通常会避免做其他事情。我认为这不是一个好主意,因为很难跟踪结构是否已强制转换(特别是如果代码很大)。此外,将其强制转换为常量并不保证以后不会将其强制转换为非常量结构
解卷提供的解决方案非常好。另一种(更明显的)解决方案是将结构分成两个较小的部分
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 ...);
我在上面的调用中也使指针保持不变,但这不是必需的。如果您不希望ext\u function
修改数据
,则应将其声明为const uint8\u t*const data代码>
typedef struct s1 { int x; } t1, *tp1;
typedef struct s2 { int x; } t2, *tp2;
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 ...);