别名结构和数组符合方式

前端之家收集整理的这篇文章主要介绍了别名结构和数组符合方式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在ISO C之前的日子里,下面的代码会让人惊讶:
struct Point {
    double x;
    double y;
    double z;
};
double dist(struct Point *p1,struct Point *p2) {
    double d2 = 0;
    double *coord1 = &p1.x;
    double *coord2 = &p2.x;
    int i;
    for (i=0; i<3; i++) {
        double d = coord2[i]  - coord1[i];    // THE problem
        d2 += d * d;
    return sqrt(d2);
}

那时,我们都知道double的对齐允许编译器在struct Point中不添加填充,我们只是假设指针算术会完成这项工作.

不幸的是,这个有问题的行使用指标算术(p [i]按定义*(p i))在任何数组之外,该标准明确不允许. C11的n1570草案在6.5.6附加操作符§8中说:

When an expression that has integer type is added to or subtracted from a pointerpointer,the
result has the type of the pointer operand. If the pointer operand points to an element of
an array object,and the array is large enough
,the result points to an element offset from
the original element such that the difference of the subscripts of the resulting and original
array elements equals the integer expression…

当我们没有相同数组的两个元素时没有说什么,它没有被标准和未定义的行为指定(即使所有常见的编译器都很高兴它…)

题:

因为这个成语允许避免代码复制只改变x和y然后z这是非常容易出错的,所以可能是一种一致的方式来浏览结构的元素,就好像它们是同一个数组的成员一样?

免责声明:它显然只适用于相同类型的元素,并且可以使用简单的static_assert检测填充,如我的that other question所示,因此填充,对齐和混合类型不是我的问题.

解决方法

C没有定义任何方式来指定编译器不能在struct Point的命名成员之间添加填充,但是许多编译器都有一个扩展来提供它.如果你使用这样的扩展,或者你只是愿意假设没有填充,那么你可以使用带有匿名内部结构的联合,如下所示:
union Point {
    struct {
        double x;
        double y;
        double z;
    };
    double coords[3];
};

然后,您可以通过各自的名称或通过coords数组访问坐标:

double dist(union Point *p1,union Point *p2) {
    double *coord1 = p1->coords;
    double *coord2 = p2->coords;
    double d2 = 0;

    for (int i = 0; i < 3; i++) {
        double d = coord2[i]  - coord1[i];
        d2 += d * d;
    }
    return sqrt(d2);
}

int main(void) {
    // Note: I don't think the inner braces are necessary,but they silence
    //       warnings from gcc 4.8.5:
    union Point p1 = { { .x = .25,.y = 1,.z = 3 } };
    union Point p2;

    p2.x = 2.25;
    p2.y = -1;
    p2.z = 0;

    printf("The distance is %lf\n",dist(&p1,&p2));

    return 0;
}

猜你在找的C&C++相关文章