c - 如何在 C 程序中鼓励未定义的行为/乱序执行?
问题描述
我正在阅读以下关于 C 中序列点的文章:https ://www.geeksforgeeks.org/sequence-points-in-c-set-1/
其中有几个未定义行为的示例,例如调用两个修改单个全局变量的函数的表达式,或多次递增同一变量的单个表达式。
理论上,我理解这个概念。但是,无论我尝试运行这些示例多少次,行为都是一样的,而且永远不会“令人惊讶”。
为了亲身体验未定义的行为,让示例“令人惊讶”的最简单方法是什么?
(如果重要的话,我正在使用 MINGW64。)
解决方案
测试 gcc 和 clang 时一个有用的模式是使用下标访问数组,下标的值将在范围内,但编译器不知道,并使用标准描述为等效于下标表示法的指针语法。使用以下内容测试 gcc 和 clang:
struct S1 {int x;};
struct S2 {int x;};
union foo { struct S1 arr1[8]; struct S2 arr2[8]; } u;
uint32_t test1(int i, int j)
{
if (sizeof u.arr1 != sizeof u.arr2)
return -99;
if (u.arr1[i].x)
u.arr2[j].x = 2;
return u.arr1[i].x;
}
uint32_t test2(int i, int j)
{
if (sizeof u.arr1 != sizeof u.arr2)
return -99;
if ((u.arr1+i)->x)
(u.arr2+j)->x = 2;
return (u.arr1+i)->x;
}
将揭示,尽管标准将 和 的行为分别定义为和,u.arr1[i].x
但gcc 和 clang 在给定前者时错过了一个允许的优化机会,而在给定后者时它们利用了。这很可能是因为作者认识到利用前一个机会是允许的,但不可否认是愚蠢的,以至于不得不承认该标准从未打算鼓励它允许的所有优化。u.arr2[j].x
(u.arr1+i)->x
(u.arr2+j)->x
推荐阅读
- reactjs - 类组件内的 react-router-dom useParams()
- java - 网页警报的事件监听器
- junit5 - jqwik - 任意地图 - 在地图中生成随机数量的条目
- javascript - 如何使用 CSS 设置 Angular Material 选项卡的样式?
- c# - 测试 - 尝试仅部分模拟接口的行为(对于现有对象)
- firebase - 从查询中排除文档
- django - Django Celery 定期手动调用
- jenkins - 将赛普拉斯与 Jenkins 集成
- elasticsearch - ElasticSearch 查询以填充或附加值到字段
- ios - 如何使用 React-Native 播放原生 ios Keyboard Touch 声音?