Is it possible to use aggregate initialization to make a pointer aptr
point to a
which is a member of the same struct
?
struct S {
int a;
int* aptr;
};
int main() {
S s = {
.a = 3,
.aptr = &a //point aptr to a
};
return 0;
}
The question is for both C
and C++
.
A working initialization would be:
struct S {
int a;
int* aptr;
};
int main() {
struct S s = {.a = 3, .aptr = &s.a};
printf("%d", *s.aptr);
}
Working samples:
C11 GNU
C++2a GNU
Regarding the correctness of the initialization:
For C:
The evaluations of the initialization list expressions are indeterminately sequenced with respect to one another and thus the order in which any side effects occur is unspecified.
For C++:
Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions ([temp.variadic]), are evaluated in the order in which they appear. That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list.
However, despite the differences we can observe, the order in which the expressions are evaluated does not seem matter in this case, since you're not actually accessing the value of s.a
, just its address which is accessible at this point.
So this is a correct initialization both for C
and C++
.
Something to note with this code, in MSVC
, there is a compilation error in C++
:
use of designated initializers requires at least '/std:c++latest'
Using std:c++latest
the error changes to:
designated and non-designated initializers is nonstandard in C++
However, compilers that range from clang 3.1
to clang 10.0
and gcc 4.9.0
to gcc 10.0
with C++03
to C++2a
compile fine with no warnings.
Designated initializers where introduced in C++20
, so it is actually correct not to accept them, as MSVC still does not accept /std:c++20
, it is not possible to use them yet, it also looks like gcc
and clang
always provided support for these initializers.
That being said, a second solution would be:
struct S {
int a;
int* aptr;
};
int main() {
struct S s = { 3, &s.a };
printf("%d", *s.aptr);
}
This second version of initialization compiles with no issues in every compiler tested, so it's fair to assume that it is more portable.
The first version is probably more easily readable and allows for a easier identification of errors in initialization, one of the advantages of designated initializers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With