当询问C中常见的未定义行为时,灵魂比我提到的严格别名规则更加开明.
他们在说什么?
我早先使用过工会; 今天,当我读到这篇文章并开始知道这段代码时,我感到震惊
union ARGB
{
uint32_t colour;
struct componentsTag
{
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
} components;
} pixel;
pixel.colour = 0xff040201; // ARGB::colour is the active member from now on
// somewhere down the line, without any edit to pixel
if(pixel.components.a) // accessing the non-active member ARGB::components
Run Code Online (Sandbox Code Playgroud)
实际上是未定义的行为即从工会成员读取而不是最近编写的那个导致未定义的行为.如果这不是工会的预期用途,那是什么?有人可以详细解释一下吗?
更新:
事后我想澄清一些事情.
如果标准布局联合包含多个共享公共初始序列的标准布局结构,并且如果此标准布局联合类型的对象包含其中一个标准布局结构,则允许检查任何标准布局结构的公共初始序列.标准布局结构成员.§9.2/ 19:如果相应的成员具有布局兼容类型且两个成员都不是位字段,或者两者都是具有相同宽度的位字段,则一个或多个初始序列的两个标准布局结构共享一个公共初始序列成员.
C89/90在未指明的行为(附件J)中称之为,而K&R的书称其实施已定义.来自K&R的报价:
这是联合的目的 - 一个可以合法地保存几种类型中的任何一种的变量.[...]只要用法一致:检索到的类型必须是最近存储的类型.程序员有责任跟踪当前存储在联合中的类型; 如果将某些内容存储为一种类型并将其提取为另一种类型,则结果将依赖于实现. …
我已经学会了但并没有真正得到工会.我经历的每一个C或C++文本都会介绍它们(有时会传递),但是它们往往只提供很少的实际例子来说明为什么或在哪里使用它们.工会什么时候可以用于现代(甚至遗留)案件?我只有两个猜测是编程微处理器,当你的空间非常有限,或者你正在开发一个API(或类似的东西),并且你想迫使最终用户只有一个对象/类型的实例一度.这两个猜测是否接近正确?
我的印象是访问union除最后一个成员之外的成员是UB,但我似乎无法找到一个可靠的参考(除了声称它是UB但没有标准支持的答案).
那么,这是不确定的行为?
基本上我正在做以下事情:
std::set<int> indices;
// ..fill indices
if (flag)
{
// we need to process in ascending order
BOOST_FOREACH (int i, indices)
{
process(i);
}
}
else
{
// we need to process in descending order
BOOST_REVERSE_FOREACH (int i, indices)
{
process(i);
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道是否有办法在C++ 03中编写相同的东西,只需要调用一个进程(i),以某种方式参数化处理顺序?像这样(显然在C++ 0x中不起作用,因为begin()和rbegin()返回不同的类型):
auto iter = flag ? indices.begin() : indices.rbegin();
auto end = flag ? indices.end() : indices.rend();
BOOST_FOREACH (int i, std::make_pair(iter, end))
{
process(i);
}
Run Code Online (Sandbox Code Playgroud)