【问题标题】:Trap representation for structures结构的陷阱表示
【发布时间】:2018-12-23 08:27:12
【问题描述】:

我想详细了解陷阱表示的概念。定义很清楚Section 3.19.4:

不需要表示对象值的对象表示 输入

好的,我想通过一些例子来试试。

struct test_t{
    uint64_t member;
};

struct test_t *test_ptr = malloc(sizeof(uint32_t));
struct test_t = *test_ptr; //1

我不认为//1 会导致这里出现 UB,因为Section 6.2.6.1

如果一个对象的存储值有这样的表示并被读取 通过没有字符类型的左值表达式, 行为未定义。

但是

结构或联合对象的值绝不是陷阱 表示,即使结构成员的值或 union 对象可能是一个陷阱表示。

我认为 UB 是由类似的东西引起的

printf("Test.member = %lu\n", test.member);

但我不确定如何证明在这种情况下member 的表示是一个陷阱。

【问题讨论】:

  • 它是 UB,但不是因为任何可能的陷阱表示。相反,它是 UB,因为您越界访问内存,读取不属于您的内存。这发生在//1
  • 只有当对象具有不用于值表示的位时,才可能使用陷阱表示。固定宽度的无符号整数类型使用它们的所有位来表示值。
  • @Someprogrammerdude 那么你能举一个结构成员的陷阱表示的例子吗?
  • @StoryTeller 但是*test_ptrlvalue,结构的值绝不是陷阱。为什么是这个UB?能给个参考吗?
  • uint64_t member; ... printf("Test.member = %lu\n", test.member); 这样的代码不必要地增加了混淆,因为"lu" 肯定不是uint64_t 的匹配打印说明符,因此printf("Test.member = %lu\n", test.member); UB 就在那里。最好使用"%" PRIu64 编码。

标签: c struct language-lawyer


【解决方案1】:

member 没有陷阱表示,因为uint64_t 没有陷阱表示。

7.20.1.1 精确宽度整数类型

2 typedef 名称 uintN_t 指定无符号整数类型 宽度为 N 且没有填充位。因此,uint24_t 表示这样一个 无符号整数类型,宽度正好为 24 位。

没有填充位。从以下部分我们了解到:

6.2.6.2 整数类型

1 对于 unsigned char 以外的无符号整数类型,位 对象表示应分为两组:值 位和填充位(不需要任何后者)。如果有 是 N 个值位,每个位应代表 2 的不同幂 在 1 和 2N - 1 之间,因此该类型的对象应为 能够使用 a 表示从 0 到 2N - 1 的值 纯二进制表示;这应称为值 表示。任何填充位的值是 未指定。53)

注释 53 尽管不规范,但告诉我们这些填充位(如果存在)可用于陷阱:

53) 一些填充位组合可能会产生陷阱 表示,例如,如果一个填充位是奇偶校验位。 无论如何,对有效值的算术运算都不能生成 陷阱表示,而不是作为异常条件的一部分 例如溢出,这不会发生在无符号类型上。全部 填充位的其他组合是替代对象 由值位指定的值的表示。

虽然值位永远不能包含非法的模式。

因此,您不能在格式良好的程序中生成uint64_t 的陷阱表示。请注意,由于越界访问,您的程序具有 UB,但这不是由陷阱表示的可能性引起的。它本身是未定义的。

【讨论】:

  • 现在使用的唯一具有陷阱表示的类型是浮点数和枚举类型。
  • 我误解了陷阱表示的概念...谢谢。
猜你喜欢
  • 2011-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多