AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 79486669
Accepted
0___________
0___________
Asked: 2025-03-05 21:41:21 +0800 CST2025-03-05 21:41:21 +0800 CST 2025-03-05 21:41:21 +0800 CST

这个声明是 UB 吗?

  • 772

考虑:

typedef union 
{
    int intval;
    const int const_intval;
}myUnion_t;

int main(void)
{
    myUnion_t x = {0};

    x.intval = 5;

    printf("intval = %d\n", x.intval);
    printf("const_intval = %d\n", x.const_intval);
}
  1. UB 本身的定义是否myUnion_t与此处相同?
  2. 有intvalUB 的作业吗?

经过测试的所有编译器均未发出警告(使用 C++ 编译器编译时也如此)

编辑

重复仅与问题有关2,与主要问题无关。

c
  • 1 1 个回答
  • 1036 Views

1 个回答

  • Voted
  1. Best Answer
    John Bollinger
    2025-03-06T00:09:12+08:002025-03-06T00:09:12+08:00
    1. UB 本身的定义是否myUnion_t与此处相同?

    不。

    • 问题中提供的联合说明符符合 C23 6.7.3.2/1 中描述的 C 语法

    • 不存在对成员是否合格或成员和非成员const混合的约束(C23 6.7.3.2/2-6)。约束是我们发现语法之上的限制,例如在通常允许合格类型的情况下,对资格的使用进行限制。constconstconst

    • C明确允许

      结构或联合的成员可以具有除变量修改类型之外的任何完整对象类型。

      (C23 6.7.3.2/11)

      const作为类型限定符,它是任何被限定成员类型的一部分。也就是说,const int是不同于 的类型int,并且属于允许用于联合成员的“任何完整类型”。

    唯一需要争论的是以 结尾的类型名称_t。C 对此没有特别的规定,但如果 POSIX 对您很重要,那么您应该知道它保留了该形式的名称。


    1. 有intvalUB 的作业吗?

    对类似问题的回答也是如此,依据第 6.4.7.1/7 段中该 C23 条款的 C11 版本:

    如果尝试const通过使用非 -限定类型的左值来修改用 -const限定类型定义的对象,则行为未定义。

    我倾向于同意,但我不认为该条款的应用是完全明确的。联合由逻辑上不同的成员组成,具有重叠的存储(C23 6.2.5/25),并且从概念上讲,联合一次只包含一个成员的值(C23 注释 38)。那么,有一个问题,将 分配给 是否x.intval应解释为修改x.const_intval。上述规定应在哪个级别应用?事实上,对于 C++ 来说,答案可能有所不同,它通过放弃基于联合的类型双关的定义行为来对联合成员进行更严格的区分——但在那里,即使赋值具有定义的行为,第二次printf()调用(x.const_intval访问 )也不会。

    不同的路径将遵循赋值操作的规范——具体来说,赋值运算符必须具有可修改的左值作为其左操作数 (C23 6.5.17.1/2)。然后,根据 C23 6.3.3.1/1,

    可修改左值是这样一种左值 [...] 如果它是一个结构或联合,则它没有任何具有 const 限定类型的成员 [...]。

    我们还知道,当使用.或->运算符通过主机结构或联合访问成员时,生成的左值的类型将继承指定主机结构或联合的左值的限定符。这意味着如果x声明了const,则分配给x.intval将具有未定义的行为。但这也不能让我们得出预期的结论,因为从类型x.intval继承了限定符x,而不是直接继承了可修改性。 x本身不是可修改的左值,但x.intval似乎满足规范对“可修改的左值”的定义。

    我认为这是规范的一个缺陷。

    最安全的解释是赋值给会产生 UB。如果随后访问,则会产生x.intval双重 UB ,如果初始化了,则会产生三重 UB。实际上,即使您更愿意将赋值给解释为具有定义的行为,但您的 C 实现也可能不具有定义的行为,因此赋值在实践中会引发程序中意外的、不需要的行为。x.const_intvalx.const_intvalx.intval

    • 15

相关问题

  • 比 * 更快的乘法

  • 在 C 中的 scanf() 格式说明符中使用宏获取字符串长度

  • 如何将#define的数据类型设置为long double?

  • 不兼容的常量指针

  • OpenGL 中的非渐变颜色变化

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve