问题
I have defined 5 floats within a struct: struct as {float a1, a2, a3, a4, a5;}; I'd like to access those 5 using a single pointer float* p_a = &a1;, and then just p_a++, etc. Will it work? Converting to array float a[5] requires a big change I would like to avoid.
回答1:
I would rather
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;
}
回答2:
You can do ++ on array-element pointers and as long as your within the array or one element past it.
Some parts of the standard (http://port70.net/~nsz/c/c11/n1570.html#K.3.9.1.2p4) consider scalars as equivalent to one element-arrays, but I wouldn't rely on it.
A safe strategy should be to do your pointer arithmetic with a character pointer and then cast to float* before use. (See https://stackoverflow.com/a/62695674/1084774 for details).
You're not technically guarantee contiguity of your struct as, but practically it will be contiguous and you can _Static_assert that it is.
Example:
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);
}
回答3:
I would like to access those 5 using a single pointer float* p_a = &a1;, and then just p_a++, etc.
p_a points at a1, which is not of array type. Pointer arithmetics is only defined within the bounds of an array, making incrementing the pointer and then dereferencing it undefined behavior.
Will it work?
Perhaps, due to the way compilers implement pointer arithmetics and memory handling. But there is no guarantee given by the language standard, so you should avoid the construct.
(For example, since the construct is not defined, the compiler is not required to "realize" that your access through that incremented pointer will change e.g. a2, and subsequent reads of a2 might give the old value because the compiler optimized away the memory access -- nothing could have changed a2, now could it?)
回答4:
The ideal solution, as noted by others, is to use an array:
struct as {
float a[5];
}
which would allow pointer arithmetic any concern.
Given that you (can't or) don't want to modify the struct, what you want to do should work practically on any implementation (but undefined in the standard) because usually padding won't exist between members of same type (but not guaranteed in the standard).
You can also consider using offsetof to check whether there are contiguous (no padding). Since offsetof works at compile-time, you can verify this on all your target architectures when building.
struct as {
float f1, f2, f3, f4, f5;
};
_Static_assert((offsetof(struct as, f1) - offsetof(struct as, f5)) != 4 * sizeof(float));
Other than that, there's no much you can do workaround the "undefined behaviour".
来源:https://stackoverflow.com/questions/62932383/accessing-struct-elements-using-single-pointer