【问题标题】:Is undefined behavior to declare a variable while passing by reference?通过引用传递时声明变量的行为是否未定义?
【发布时间】:2025-12-13 23:15:01
【问题描述】:

来自 cppreference:

在上一个和下一个序列点之间,一个标量对象必须有 它的存储值最多修改一次由评估 表达式,否则行为未定义。

代码示例:

int a = store_and_return_value(&a);

对于 C 和 C++。

【问题讨论】:

  • @t.niese 如果可能的话,我想知道 C 和 C++ :)
  • 2011年C++废除了序列点的概念,cppreference页面需要更新。我正在从这个问题中删除 C++ 标记,但可以随意添加一个新问题。
  • @Brian -- 序列点的概念没有被废除; 术语已更改。目的是保留以前应用的规则。
  • @PeteBecker 我同意这样做的目的是保留以前应用的规则,但这个概念也确实变成了更通用的规则。
  • @PatrickJoséPereira 回复:“i = i++ + 1 是 UB” 直到 C++17

标签: c


【解决方案1】:

不会表现出未定义的行为。

C standard 的第 6.5.2.3p10 节指出:

评估后有一个序列点 函数指示符和实际参数,但在实际之前 调用。 调用函数中的每个评估(包括其他 函数调用)没有特别排序的 在被调用函数的主体执行之前或之后是 关于被调用的执行顺序不确定 功能

所以给定你的代码行:

int a = store_and_return_value(&a);

对函数store_and_return_value 的调用引入了一个序列点。假设函数中有类似*arg = 123;的行,那么这句话后面还有一个序列点。

因此,store_and_return_value 内任何取消引用并写入传入指针的语句都在a 正式初始化之后排序。因此,无论store_and_return_value 的主体包含什么,程序都是定义良好的。

【讨论】:

    【解决方案2】:

    int a = scanf("%d", &a); 没有表现出未定义的行为。

    这些是明确定义的步骤:

    1. 在名为 a 的堆栈上创建了一个 int 变量

    2. scanf 将标准输入中的值读入a

    3. scanf 返回一个值

    4. 这个返回值赋值给a

    a 的最终值由scanf 的返回值决定,1(如果a 的一个变量被读取成功)或0(读取失败)。

    编辑:

    答案是在问题被编辑之前写的

    int a = store_and_return_value(&a);

    这里也有同样的道理。

    【讨论】:

      最近更新 更多