问题标签 [undefined-behavior]
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.
c - 在C语言中,如果我强制转换和取消引用一个指针,我先做哪个有关系吗?
在 C 中,您可以转换简单的数据类型,如int
,float
和指向这些的指针。
现在我假设如果你想从指向一种类型的指针转换为另一种类型的值(例如 from *float
to int
),强制转换和取消引用的顺序无关紧要。即对于一个变量float* pf
,你有(int) *pf == *((int*) pf)
. 有点像数学中的交换律...
然而,情况似乎并非如此。我写了一个测试程序:
在我的系统上,输出是
因此,转换指针似乎与转换值的工作方式不同。
这是为什么?为什么第二个版本没有做我认为应该做的事?
这是平台相关的,还是我以某种方式调用未定义的行为?
c++ - 重新加载未定义的行为和序列点
将此主题视为以下主题的续集:
上一部分
未定义的行为和序列点
让我们重温一下这个有趣而复杂的表达方式(斜体词组取自上述主题 *smile* ):
我们说这调用了未定义的行为。我假设当这样说时,我们隐含地假设type ofi
是内置类型之一。
如果类型是i
用户定义的类型怎么办?说它的类型是Index
本文后面定义的类型(见下文)。它还会调用未定义的行为吗?
如果是,为什么?它不等同于写作i.operator+=(i.operator++());
甚至语法上更简单 i.add(i.inc());
吗?或者,他们是否也调用了未定义的行为?
如果没有,为什么不呢?毕竟,对象在连续序列点之间i
被修改了两次。请回忆一下经验法则:一个表达式只能在连续的“序列点”之间修改一个对象的值。如果 i += ++i
是一个表达式,那么它必须调用 undefined-behavior。如果是这样,那么它的等价物i.operator+=(i.operator++());
也 i.add(i.inc());
必须调用 undefined-behavior似乎是不真实的!(据我了解)
或者,i += ++i
不是一个表达式开始吗?如果是这样,那么它是什么,表达的定义是什么?
如果它是一个表达式,同时它的行为也是明确定义的,那么它意味着与表达式关联的序列点的数量在某种程度上取决于表达式中涉及的操作数的类型。我是否正确(甚至部分正确)?
顺便问一下,这个表情怎么样?
您也必须在回复中考虑到这一点(如果您确定知道它的行为)。:-)
是
在 C++03 中定义良好?毕竟是这个,
c - 结构的联合是否共享第一个元素未定义的行为?
SDL_Event是无符号 8 位类型和许多第一个元素是无符号 8 位类型的结构的联合。推荐的用法是访问 union 的 Uint8 元素来确定事件是什么类型,然后通过适合该类型的元素访问 union。
这显然取决于联合中的所有类型都为类型标识符保留相同的空间。我们可以确定是这种情况,还是这种未定义的行为?
编辑:使标题更具描述性。
c - += 运算符链接(带有一点 UB)
我知道分号之前没有序列点,但是对于取消引用的指针在表达式中使用旧值 2 是否有合理的解释?
还是可以简单地将其归结为未定义的行为?
结果:
c - 指针类型之间的转换何时不是 C 中未定义的行为?
作为 C 的新手,我很困惑何时投射指针实际上是可以的。
据我了解,您几乎可以将任何指针类型转换为任何其他类型,编译器会让您这样做。例如:
但是,通常这会调用未定义的行为(尽管它恰好在许多平台上工作)。这就是说,似乎有一些例外:
- 你可以
void*
自由地来回投射(?) - 你可以
char*
自由地来回投射(?)
(至少我在代码中见过它......)。
那么指针类型之间的哪些强制转换不是C 中未定义的行为?
编辑:
我尝试研究 C 标准(“6.3.2.3 指针”部分,位于http://c0x.coding-guidelines.com/6.3.2.3.html),但除了关于void*
.
编辑2:
只是为了澄清:我明确地只询问“正常”指针,即不询问函数指针。我意识到转换函数指针的规则非常严格。事实上,我已经问过这个问题了:-):如果我转换一个函数指针,改变参数的数量会发生什么
c - sizeof(""+0) != sizeof(char *) 错误或未定义的行为?
以下 C 程序:
1 4 4
在 Linux 上使用 GCC 编译时输出,但在1 1 4
Windows 上使用 Microsoft Visual C++ 编译时输出。GCC 结果是我所期望的。它们不同是因为 MSVC 有错误还是因为sizeof(""+0)
未定义?对于这两种编译器,无论您使用什么字符串文字或整数常量,其行为(即打印的中间值是等于第一个值还是最后一个值)都是相同的。
ANSI C 标准中的相关参考似乎是 6.2.2.1 - Lvalues and function designators:
除非它是 sizeof 运算符的操作数...类型为“类型数组”的左值被转换为类型为“类型指针”的表达式,该类型指向数组对象的初始元素,而不是左值。
在这里,虽然“除外”不应该适用,因为在sizeof(""+0)
数组/字符串文字中是+
not的操作数sizeof
。
c++ - 混合类和结构
我很清楚class 和 struct 之间的区别,但是我很难权威地说这是否定义明确:
如果这是未定义的行为,有人可以指出权威(即 ISO 中的章节和诗句)参考的方向吗?
处理此问题的编译器(Carbide 2.7)相对较旧,我尝试过的所有其他编译器对此都非常满意,但显然这并不能证明任何事情。
我的直觉是这应该是未定义的行为,但我找不到任何东西来证实这一点,我很惊讶 GCC 版本或Comeau都没有警告过它。
c - 表达式 x[--i] = y[++i] = z[i++],先计算哪个?
当左值的求值先于右值的求值并且赋值也返回一个值时,以下哪个是最先求值的?
注意:首先使用 l 值评估的通用类 C 语言。从我的教科书:
在某些语言中,例如 C,赋值被认为是一个运算符,其评估除了产生副作用外,还返回由此计算的 r 值。因此,如果我们用 C 编写:
对这样一个命令的求值,除了将值 2 赋给 x 外,还返回值 2。因此,在 C 中,我们也可以这样写:
这应该解释为: