通用写入结构指针

时间:2017-02-17 20:58:03

标签: c language-lawyer

6.2.5p28

  

指向void的指针应具有相同的表示和对齐方式   要求作为指向字符类型的指针.48)同样,指针   合格或不合格版本的兼容类型应具备   相同的表示和对齐要求。 指向的所有指针   结构类型应具有相同的表示和对齐方式   彼此的要求。所有指向联合类型的指针都应该具有   相同的表示和对齐要求。指针   其他类型不需要具有相同的表示或对齐   要求。

这是否意味着我可以一般性地写入结构指针,如:

struct a_struct;

int 
alloc_struct(struct a_struct **X, size_t Sz)
{
    if ((*X=malloc(Sz))) 
        return 0;
    return -ENOMEM;
}

struct foo{ int x; char buf[32]; };;

int main()
{
    struct foo *foo_p;
    alloc_struct((struct a_struct**)&foo_p, sizeof(*foo_p));
}

2 个答案:

答案 0 :(得分:3)

因为支持各种别名的成本在不同平台之间会有很大差异(浮点数和整数之间的别名特别昂贵),并且因为不同类型的应用程序对别名有不同的需求,所以C89标准的作者没有努力描述针对任何特定平台或应用程序字段的实现应支持的所有表单。现有的实现已经在有用的情况下支持别名,并且标准的作者没有理由期望它们停止。

没有理由认为质量实施无法支持 构造,例如您描述的构造,特别是在编译器的情况下 能够在函数调用中看到对struct a_struct**的强制转换,并且只能通过struct a_struct**访问指针的目标,但是一些实现者认为标准未能强制支持这样的构造,即暗示判断支持这样的结构没有任何好处。

因此,有两种方法可以实现您所寻求的语义:(1)通过读取和写入其中的单个字符来操纵指针(在某些情况下,有效类型会使memcpy / memmove (2)禁用基于类型的别名,并在适当的位置添加restrict限定符,以使代码比启用基于类型的别名更有效。

答案 1 :(得分:2)

不,你仍然违反了严格的别名。

类型struct a_struct*struct foo*不兼容,并且不在此规则的例外列表中。

int定义为float

并没有什么不同
int a;
int* b = a;
float* c = ( float* )b;
*c = 1.0f;

或将int*别名为float*,这是您的示例所做的,除非它们是结构指针:

int* a;
int** b = &a;
float** c = ( float** )b;
*c = NULL;

即使两个指针具有相同的对齐和表示,类型也不能别名,因为它们不兼容。