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.

- 8,198
- 18
- 69
- 133
-
What about changing the struct to have a `union` of the array and the 5 members? IIRC that should be well-defined by the standard (although I'm unsure whether struct padding can mess with this) – UnholySheep Jul 16 '20 at 10:13
-
It technically *could* work dependent upon the implementation as how it stores the members in the structure. I don't know if this a violation of any standard term nonetheless. – RobertS supports Monica Cellio Jul 16 '20 at 10:18
-
[This](https://stackoverflow.com/questions/39461364/) could be useful. – RobertS supports Monica Cellio Jul 16 '20 at 10:19
-
@pmg `p_a + 4` causes undefined behaviour (pointer arithmetic can only occur within bounds of an array, with scalars counting as array of size 1 for this purpose) – M.M Jul 16 '20 at 10:21
-
Just when I thought there could be no more tricky (silly?) C pointer questions... – Danijel Jul 16 '20 at 10:23
-
Just out of curiosity: Why is this such a big change? Do you already have a big amount of code using the structure's fields that way? – RobertS supports Monica Cellio Jul 16 '20 at 10:29
-
@RobertSsupportsMonicaCellio Exactly, a lot of code uses the struct fields. – Danijel Jul 16 '20 at 10:31
-
@Danijel I think P__J__'s solution should then work for you quite well. – Petr Skocik Jul 16 '20 at 10:52
-
@M.M AFAIK the standard doesn't actually forbid the arithmetics with the pointer itself. To dereference this pointer is clearly stated as undefined behavior. – RobertS supports Monica Cellio Jul 16 '20 at 11:02
-
@RobertSsupportsMonicaCellio it's clearly forbidden if you read the paragraph defining pointer arithmetic – M.M Jul 16 '20 at 11:12
-
@M.M Do you mean §6.5.6/8? I read only only that "*the evaluation should not produce an overflow*" and "*If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated.*" – RobertS supports Monica Cellio Jul 16 '20 at 11:21
-
@RobertSsupportsMonicaCellio "If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined". `p_a +4` does not point to an element of the same array object as `p_a` does – M.M Jul 16 '20 at 11:32
4 Answers
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;
}

- 58,047
- 6
- 95
- 142

- 60,014
- 4
- 34
- 74
-
-
2Won't `f1`..`f5` share same memory location as they are not in a nested struct? – Gerhardh Jul 16 '20 at 10:48
-
So, it possible that one can use all three notations, accessing via pointer `*p = something;`, accessing via array element `s.fa[0] = something;` or accessing via object `s.f1 = something;` and all three methods access the same memory if `p == &(s.f1)`, right? – RobertS supports Monica Cellio Jul 16 '20 at 11:52
-
1@RobertSsupportsMonicaCellio also pointer arithmetics *p = s.fa; *(p+3) = something; – 0___________ Jul 16 '20 at 12:09
-
-
This union-based approach is not strictly conforming, as it relies on the struct inside the union to be laid out the same as an array, which the Standard does not require. If strict conformance is not a concern, however, then this is fairly likely to work in practice. – John Bollinger Jul 23 '20 at 14:09
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?)

- 67,862
- 21
- 134
- 209
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);
}

- 58,047
- 6
- 95
- 142
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".

- 117,907
- 20
- 175
- 238