C 未定义的行为是否必须定义才能定义?

C 未定义的行为是否必须定义才能定义?,c,undefined-behavior,C,Undefined Behavior,尽管出现了标题,但这不是一个哲学问题 然而,严格来说,它是关于语义的 背景 在前面的编辑中,它指出读取未初始化的值是未定义的行为。我同意这个评估。其他人则不然 经过一番挖掘,我得出结论:无论是未定义的行为,都是未定义的 本标准6.3.2.1中的第2小节仅说明访问未初始化对象 […]可以用寄存器存储类[…]声明 这是一种未定义的行为 其他部分,如6.7.9[初始值设定项]或6.5.2.1[数组订阅]没有提到访问未初始化的值 因此,毫无疑问,是否有人提到这个特殊案例被标准称为未定义行为 语义学 然而

尽管出现了标题,但这不是一个哲学问题

然而,严格来说,它是关于语义的

背景 在前面的编辑中,它指出读取未初始化的值是未定义的行为。我同意这个评估。其他人则不然

经过一番挖掘,我得出结论:无论是未定义的行为,都是未定义的

本标准6.3.2.1中的第2小节仅说明访问未初始化对象

[…]可以用寄存器存储类[…]声明

这是一种未定义的行为

其他部分,如6.7.9[初始值设定项]或6.5.2.1[数组订阅]没有提到访问未初始化的值

因此,毫无疑问,是否有人提到这个特殊案例被标准称为未定义行为

语义学 然而:3.4.3 1指出,未定义的行为是

使用不可移植或错误的程序结构或错误的数据时的行为, 本国际标准对其无任何要求

从未初始化的数组中读取

  • 使用错误数据
  • 使用不可移植的构造。(即内存分配的细节1)
  • 导致行为,这已经发生了
  • 标准没有要求产生可预测的效果
我称之为“未定义的行为”。 但也许我错过了什么(?)

更广泛的问题仍然是:

行为是否必须明确提及,才能被视为“未定义的行为”

注:

  • 这个问题是针对C语言及其社区的
  • 问题在于语义学。它并不质疑从未初始化的数组读取是否“合理”。(不是,除非你是笔测试员)
  • 我使用了C11标准的草稿
脚注:

  • malloc
    calloc
    等等,确实对如何执行分配有要求。但声明固定长度数组并没有指定未初始化数据的性质

  • 当对象未初始化时,它具有不确定的*值。仅当此值是陷阱表示时,访问此对象才会调用未定义的行为。
    这说明你所指的答案有错误的推理。是正确的


    *不确定值:
    未指定的值或陷阱表示法
    未指定的值:
    相关类型的有效值,在任何情况下,本国际标准均未对选择的值提出任何要求
    注意未指定的值不能是陷阱表示法
    陷阱表示法:
    不需要表示对象类型值的对象表示法
    (§3.19.2, §3.19.3, §3.19.4)

    当对象未初始化时,它具有不确定*值。仅当此值是陷阱表示时,访问此对象才会调用未定义的行为。
    这说明你所指的答案有错误的推理。是正确的


    *不确定值:
    未指定的值或陷阱表示法
    未指定的值:
    相关类型的有效值,在任何情况下,本国际标准均未对选择的值提出任何要求
    注意未指定的值不能是陷阱表示法
    陷阱表示法:
    不需要表示对象类型值的对象表示法
    (§3.19.2, §3.19.3, §3.19.4)

    否,未定义、禁止“不得”或明确标记为未定义的行为是未定义的。以下是C标准第4条“合规性”第2段中对这些内容的定义:

    如果“应”或“不应”要求出现在 违反了约束或运行时约束,则行为为 未定义。未定义的行为在本文件中另有说明 国际标准中的“未定义行为”或 遗漏任何明确的行为定义。没有 三者的侧重点不同;它们都描述了“行为” 这是未定义的”


    不,未定义、禁止“不得”或明确标记为未定义的行为是未定义的。以下是C标准第4条“合规性”第2段中对这些内容的定义:

    如果“应”或“不应”要求出现在 违反了约束或运行时约束,则行为为 未定义。未定义的行为在本文件中另有说明 国际标准中的“未定义行为”或 遗漏任何明确的行为定义。没有 三者的侧重点不同;它们都描述了“行为” 这是未定义的”


    C89标准主要是从描述性而非规定性的角度编写的,当时许多操作都会有一些(而不是所有)实现所指定的行为,这在很大程度上取决于目标平台和应用领域。此外,许多行动在某些情况下会产生可预测和易于说明的后果,而在其他情况下则不会。该标准的作者没有努力详尽地描述当质量实施应预期表现为可预测时的所有情况组合,甚至在其基本原理文件中指出,质量足够差的实施可能同时符合要求且无用

    参考从数组中读取未初始化的数据,考虑下面的代码:

    float test(int a, int b, int c, int d)
    {
      float result;
      float *f = malloc(10*sizeof float);
      f[a] = 1.0f; f[b] = 2.0f; f[c] = 3.0f;
      result = f[d];
      free(f);
      return result;
    }
    
    在某些平台上,尝试将某些位模式作为floati处理
    typedef struct { float v; } flt;
    
    flt test2(int a, int b, int c, int d)
    {
      flt result;
      flt *f = malloc(10*sizeof flt);
      f[a].v = 1.0f; f[b].v = 2.0f; f[c].v = 3.0f;
      result = f[d];
      free(f);
      return result;
    }