C 使用单指针访问结构元素?

C 使用单指针访问结构元素?,c,pointers,memory,struct,C,Pointers,Memory,Struct,我在一个结构中定义了5个浮点:struct为{float a1,a2,a3,a4,a5;}我想使用单个指针访问这5个变量float*p_a=&a1,然后只是p_a++,等等。它会工作吗?转换为数组浮点a[5]需要一个我希望避免的大的更改。我宁愿 typedef struct { union { float fa[5]; struct { float f1,f2,f3,f4,f5; }; }; /* .... */ }MY_T;

我在一个结构中定义了5个浮点:
struct为{float a1,a2,a3,a4,a5;}我想使用单个指针访问这5个变量
float*p_a=&a1,然后只是
p_a++
,等等。它会工作吗?转换为数组
浮点a[5]
需要一个我希望避免的大的更改。

我宁愿

typedef struct
{
    union
    {
        float fa[5];
        struct { float f1,f2,f3,f4,f5; };
    };
    /* .... */
}MY_T;


void foo()
{
    MY_T s;

    float *p = s.fa;

    p++
    *p = something;
}
我宁愿

typedef struct
{
    union
    {
        float fa[5];
        struct { float f1,f2,f3,f4,f5; };
    };
    /* .... */
}MY_T;


void foo()
{
    MY_T s;

    float *p = s.fa;

    p++
    *p = something;
}
我想使用单指针浮点*p_a=&a1;访问这5个;,然后就是p_a++,等等

p_a
指向
a1
,它不是数组类型。指针算术仅在数组的边界内定义,使指针递增,然后取消对它的引用是未定义的行为

行吗

也许是因为编译器实现指针算术和内存处理的方式。但是语言标准没有提供任何保证,因此您应该避免构造

(例如,由于未定义构造,编译器不需要“实现”您通过递增指针的访问将发生更改,例如,
a2
,后续读取
a2
可能会给出旧值,因为编译器优化了内存访问——没有任何更改,现在可以吗?)

我想使用单指针浮点*p_a=&a1;访问这5个;,然后就是p_a++,等等

p_a
指向
a1
,它不是数组类型。指针算术仅在数组的边界内定义,使指针递增,然后取消对它的引用是未定义的行为

行吗

也许是因为编译器实现指针算术和内存处理的方式。但是语言标准没有提供任何保证,因此您应该避免构造


(例如,由于未定义构造,编译器不需要“实现”您通过递增指针的访问将发生更改,例如,
a2
,后续读取
a2
可能会给出旧值,因为编译器优化了内存访问——没有任何更改,现在可以吗?)

您可以对数组元素指针执行
++
,只要您的指针在数组中或一个元素通过它

标准()的某些部分认为标量相当于一个元素数组,但我不依赖它。< /P> 一个安全的策略应该是使用字符指针进行指针运算,然后在使用之前转换为

float*
。(详情请参见)

从技术上讲,您不能保证
结构作为
的连续性,但实际上它是连续的,您可以断言它是连续的

例如:

struct as {float a1, a2, a3, a4, a5;};

_Static_assert(sizeof(struct as)==sizeof(float[5]),"");

float *subscript_struct_as(struct as *X, unsigned Ix)
{
    return (float*)((char*)X + sizeof(float)*Ix);
}

您可以对数组元素指针执行
++
,只要您的指针在数组中或一个元素通过它

标准()的某些部分认为标量相当于一个元素数组,但我不依赖它。< /P> 一个安全的策略应该是使用字符指针进行指针运算,然后在使用之前转换为

float*
。(详情请参见)

从技术上讲,您不能保证
结构作为
的连续性,但实际上它是连续的,您可以断言它是连续的

例如:

struct as {float a1, a2, a3, a4, a5;};

_Static_assert(sizeof(struct as)==sizeof(float[5]),"");

float *subscript_struct_as(struct as *X, unsigned Ix)
{
    return (float*)((char*)X + sizeof(float)*Ix);
}

正如其他人所指出的,理想的解决方案是使用阵列:

struct as {
    float a[5];
}
这就不必担心了

考虑到您(不能或)不想修改结构,您想做的实际上应该适用于任何实现(但在标准中未定义),因为通常在相同类型的成员之间不存在填充(但在标准中不保证)

你也可以考虑使用<代码> Outs/<代码>检查是否有连续的(没有填充)。由于

offsetof
在编译时工作,因此在构建时可以在所有目标体系结构上验证这一点

struct as {
    float f1, f2, f3, f4, f5;
};

_Static_assert((offsetof(struct as, f1) - offsetof(struct as, f5)) != 4 * sizeof(float));

除此之外,对于“未定义的行为”,您没有什么可以做的。

正如其他人所指出的,理想的解决方案是使用数组:

struct as {
    float a[5];
}
这就不必担心了

考虑到您(不能或)不想修改结构,您想做的实际上应该适用于任何实现(但在标准中未定义),因为通常在相同类型的成员之间不存在填充(但在标准中不保证)

你也可以考虑使用<代码> Outs/<代码>检查是否有连续的(没有填充)。由于

offsetof
在编译时工作,因此在构建时可以在所有目标体系结构上验证这一点

struct as {
    float f1, f2, f3, f4, f5;
};

_Static_assert((offsetof(struct as, f1) - offsetof(struct as, f5)) != 4 * sizeof(float));

除此之外,在“未定义的行为”问题上没有什么可以做的。

将结构更改为数组和5个成员的
并集如何?IIRC应该由标准很好地定义(尽管我不确定结构填充是否会影响这一点),它在技术上可以根据实现来工作,因为它如何在结构中存储成员。我不知道这是否违反了任何标准条款。可能很有用。@pmg
p_a+4
导致未定义的行为(指针运算只能在数组的边界内发生,为此目的,标量作为大小为1的数组计数),就在我认为没有更棘手的时候(愚蠢?)C指针问题…将结构更改为数组和5个成员的
并集如何?IIRC应该由标准很好地定义(尽管我不确定结构填充是否会影响这一点),它在技术上可以根据实现来工作,因为它如何在结构中存储成员。我不知道这是否违反了任何标准条款。可能有用。@pmg
p_a+4
会导致未定义的行为(指针运算只能在数组的边界内发生,标量作为大小为1的数组计算)