首页 > 解决方案 > 结构的陷阱表示

问题描述

我想详细了解陷阱表示概念。定义很明确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

如果对象的存储值具有这样的表示形式并且由不具有字符类型的左值表达式读取,则行为未定义。

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

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

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

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

标签: cstructlanguage-lawyer

解决方案


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

7.20.1.1 精确宽度整数类型

2 typedef 名称 uint N _t 指定宽度为N且无填充位的无符号整数类型。因此,uint24_t 表示这种无符号整数类型,其宽度正好为 24 位。

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

6.2.6.2 整数类型

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

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

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

而值位永远不能保存非法的模式。

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


推荐阅读