问题标签 [strict-aliasing]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
4 回答
3053 浏览

c++ - 浮点位和严格的别名

我试图从浮点数中提取位而不调用未定义的行为。这是我的第一次尝试:

据我了解,由于严格的别名规则,这不能保证有效,对吧?如果使用字符指针采取中间步骤,它会起作用吗?

还是我必须自己提取单个字节?

当然,这有依赖字节序的缺点,但我可以忍受。

union hack 绝对是未定义的行为,对吧?

为了完整起见,这里是一个参考版本foo。还有未定义的行为,对吗?

那么,是否可以从浮点数中提取位(当然,假设两者都是 32 位宽)?


编辑:这是memcpyGoz 提出的版本。由于许多编译器尚不支持static_assert,因此我已替换static_assert为一些模板元编程:

0 投票
4 回答
1935 浏览

c++ - 在这种情况下可以转换指向成员变量的指针吗?

我最近一直在刷新/更新我对 C++ 的了解,并且学习严格的别名让我对将一种类型的指针转​​换为另一种类型的指针有点警惕。我知道以下代码示例在我的编译器上实际工作,但我想确保它符合当前标准:

本质上,这个简单的元组包含一对元素,每个元素都应该派生自一个公共基类。Get 函数将 a 返回Base*给给定索引表示的成员。

我想知道的关键部分是 reinterpret_casts。我知道从Derived Struct::*to转换Base Struct::*通常禁止的,但在这种情况下,我只使用指向成员变量的指针来获取指向对象的指针。(我不会尝试将派生对象复制为基础对象,也不会将基础对象填充到派生对象的内存中。)这在 G++ 上按预期工作,我只是想确定我不是这样做会被任何兼容的编译器咬伤。

0 投票
3 回答
417 浏览

c++ - 执行变量原始副本的简单转换是否会破坏严格的别名?

我最近一直在阅读有关严格混叠的文章。C/C++ 标准说以下代码是无效的(未定义的行为是正确的),因为编译器可能在a某处缓存了值,并且在我更新时不会识别它需要更新值b

该标准还说char*可以为任何东西加上别名,因此(如果我错了,请纠正我)编译器会在对char*变量进行写访问时重新加载所有缓存的值。因此,以下代码将是正确的:

但是在根本不涉及指针的情况下呢?例如,我有以下代码,GCC 会向我抛出关于严格别名的警告。

我想要做的只是复制原始值a,所以不应该应用严格的别名。这里是否存在可能的问题,或者只是 GCC 对此过于谨慎?

编辑

我知道有一个使用memcpy的解决方案,但它导致代码的可读性要差得多,所以我不想使用那个解决方案。

编辑2

int32_t b = *reinterpret_cast<int*>(&a);也不起作用。

解决了

这似乎是GCC 中的一个错误

0 投票
3 回答
426 浏览

c++ - 带 -O2 和不带 -O2 的移位运算符的不同行为

如果没有 -O2,此代码将打印84 84,带有 O2 标志的输出为84 42gcc 4.4.3.该代码是在 64 位 Linux 平台上编译的。为什么以下代码的输出不同?

请注意,使用 -Os 编译时,输出为0 42

0 投票
1 回答
277 浏览

c++ - 类型别名和动态分配的数组

我正在尝试通过 blitz++ 数组库中的编译器来促进自动矢量化。出于这个原因,我想展示固定长度向量块中的数组数据的视图,这些向量已经很好地向量化了。但是,我无法弄清楚类型别名规则与动态分配的数组一起意味着什么。

这是想法。一个数组目前包括

操作是通过循环这些数据来完成的。我想做的是将此数组的另一种视图呈现为 的数组TinyVector<T_numtype, N>,它是一个固定长度的向量,其操作使用表达式模板机制完全向量化。这个想法是 L 长度数组应该是T_numtype[L]or TinyVector<T_numtype, N>[L/N]。有没有办法在不违反类型令人震惊的规则的情况下做到这一点?

对于静态分配的数组,可以这样做

我能想到的最接近的是定义

然后分配它

但似乎现在我已经放弃了将整个数组作为 T_numtype 的平面数组来寻址的权利,因此要访问特定元素,我需要这样做data_[i/N].data_[i%N],这要复杂得多。

那么,有没有一种方法可以合法地创建一个并集T_numtype data_[L]TinyVector<T_numtype, N>[L/N]其中 L 是一个动态确定的大小?

(我知道还有其他对齐问题,即 N 必须是与 TinyVector 成员的对齐方式相同的值,否则数组中会有孔。)

0 投票
3 回答
7057 浏览

c++ - gcc:如何正确使用 __attribute((__may_alias__)) 以避免“取消引用类型双关指针”警告

我有一些使用类型双关语的代码,以避免调用成员“对象”的构造函数和析构函数,除非/直到实际上有必要使用该对象。

它工作正常,但在 g++ 4.4.3 下,我收到了这个可怕的编译器警告:

我的代码尝试使用 gcc 的 __attribute((__may_alias__)) 让 gcc 知道潜在的别名,但 gcc 似乎不明白我想告诉它什么。我做错了什么,还是 gcc 4.4.3 的 __may_alias__ 属性有一些问题?

重现编译器警告的玩具代码如下:

0 投票
3 回答
855 浏览

c++ - 为什么将指针转换回原始类时会出现奇怪的行为?

假设在我的代码中,我必须将一个void*作为数据成员存储并在需要时将其类型转换回原始class指针。为了测试它的可靠性,我写了一个测试程序(linux ubuntu 4.4.1 g++ -04 -Wall),看到这个行为我很震惊。

这只是一个测试程序;实际上,对于我的情况,必须将任何指针存储为void*,然后将其转换回实际指针(在 的帮助下template)。所以我们不要担心那部分。上述代码的输出是,

但是,如果您将其更改void* p;A* p;它会给出预期的行为为什么 ?

另一个问题,我无法逃避,(A*&)否则我无法使用operator ++;但它也会发出警告,因为取消引用类型双关指针会破坏严格的别名规则。有什么体面的方法来克服警告吗?

0 投票
1 回答
825 浏览

c++ - 为什么boost :: optional对于继承虚函数的类会失败

boost::optional<> 适用于简单的数据类型,但一旦用于从实现接口的类继承的类,当启用严格别名时它会失败。

例子:

使用 gcc 版本 4.4.3 编译以下错误:

解决此问题的最佳方法是什么。我非常想启用严格混叠警告。我使用的是 boost 1.44 版。

更新:

变得更糟了!!考虑以下代码:

使用 gcc 版本 4.4.3 编译如下:

如果标有“//comment out for surprise”的行被注释掉,我会收到严格的别名警告。我已经检查了至少 20 次。这是我见过的最奇怪的事情之一。看起来 boost::optional 初始化了某事。独立于它的模板参数,或者像 gcc 一样,只有在使用 sth 调用时才能理解 boost::optional。先琐碎。有任何想法吗 ?

0 投票
1 回答
584 浏览

c - C 克服别名限制(联合?)

假设我有一个示例源文件 test.c,我正在编译它:

$ gcc -03 -墙

test.c 看起来像这样..

假设我接受这样的限制,如果你传入两个重叠的指针,你会得到未定义的结果。

我已经尝试过这样的事情(想象这些宏在每行末尾用反斜杠转义的换行符正确格式化)

但是当我在宏 (a[0] < b[0]) 中取消引用 a 时,我从 gcc 收到“取消引用破坏严格别名规则”错误

我原以为你应该使用联合以两种不同的方式正确引用内存中的一个地方,所以接下来我尝试了类似的东西

除了我从编译器那里得到关于严格别名规则的完全相同的错误。

那么:有没有办法在不破坏严格混叠的情况下做到这一点,而不是实际复制内存?

may_alias不算,它只是让你绕过严格的别名规则)

编辑:使用 memcmp 来做到这一点。我被混叠规则赶上了,并没有想到它。

0 投票
2 回答
532 浏览

c++ - SSE 数据类型和原语

在网上的大多数教程或代码片段中,可以看到以下内容:

这是否违反了严格的别名规则?我认为确实如此,但是所有那些教程作者肯定不会为了方便而忽略它,因为 __m128 是一个包含 float[4] 的联合,也许我误解了它的一些复杂部分。