聚合初始化,将成员指针设置为相同的结构成员
Aggregate initialization, set member pointer to same struct member
是否可以使用聚合初始化使指针 aptr
指向 a
,后者是同一个 struct
的成员?
struct S {
int a;
int* aptr;
};
int main() {
S s = {
.a = 3,
.aptr = &a //point aptr to a
};
return 0;
}
问题针对 C
和 C++
。
工作初始化为:
struct S {
int a;
int* aptr;
};
int main() {
struct S s = {.a = 3, .aptr = &s.a};
printf("%d", *s.aptr);
}
工作样本:
关于初始化的正确性:
对于 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.
对于 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.
然而,尽管我们可以观察到差异,但在这种情况下,表达式求值的顺序似乎并不重要,因为您实际上并没有访问 s.a
的值,只是访问它的地址此时可以访问。
所以这是 C
和 C++
.
的正确初始化
这段代码需要注意的地方,在MSVC
中,在C++
中存在编译错误:
use of designated initializers requires at least '/std:c++latest'
使用std:c++latest
错误变为:
designated and non-designated initializers is nonstandard in C++
但是,从 clang 3.1
到 clang 10.0
和 gcc 4.9.0
到 gcc 10.0
和 C++03
到 C++2a
编译正常,没有警告。
在C++20
中引入的指定初始化器,所以不接受它们实际上是正确的,因为MSVC仍然不接受/std:c++20
,它是还不能使用它们,看起来 gcc
和 clang
总是提供对这些初始化程序的支持。
也就是说,第二种解决方案是:
struct S {
int a;
int* aptr;
};
int main() {
struct S s = { 3, &s.a };
printf("%d", *s.aptr);
}
第二个版本的初始化在每个测试的编译器中都没有问题,因此可以假设它更便携。
第一个版本可能更易于阅读,并且更容易识别初始化中的错误,这是指定初始化器的优点之一。
是否可以使用聚合初始化使指针 aptr
指向 a
,后者是同一个 struct
的成员?
struct S {
int a;
int* aptr;
};
int main() {
S s = {
.a = 3,
.aptr = &a //point aptr to a
};
return 0;
}
问题针对 C
和 C++
。
工作初始化为:
struct S {
int a;
int* aptr;
};
int main() {
struct S s = {.a = 3, .aptr = &s.a};
printf("%d", *s.aptr);
}
工作样本:
关于初始化的正确性:
对于 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.
对于 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.
然而,尽管我们可以观察到差异,但在这种情况下,表达式求值的顺序似乎并不重要,因为您实际上并没有访问 s.a
的值,只是访问它的地址此时可以访问。
所以这是 C
和 C++
.
这段代码需要注意的地方,在MSVC
中,在C++
中存在编译错误:
use of designated initializers requires at least '/std:c++latest'
使用std:c++latest
错误变为:
designated and non-designated initializers is nonstandard in C++
但是,从 clang 3.1
到 clang 10.0
和 gcc 4.9.0
到 gcc 10.0
和 C++03
到 C++2a
编译正常,没有警告。
在C++20
中引入的指定初始化器,所以不接受它们实际上是正确的,因为MSVC仍然不接受/std:c++20
,它是还不能使用它们,看起来 gcc
和 clang
总是提供对这些初始化程序的支持。
也就是说,第二种解决方案是:
struct S {
int a;
int* aptr;
};
int main() {
struct S s = { 3, &s.a };
printf("%d", *s.aptr);
}
第二个版本的初始化在每个测试的编译器中都没有问题,因此可以假设它更便携。
第一个版本可能更易于阅读,并且更容易识别初始化中的错误,这是指定初始化器的优点之一。