UB是否可以抛弃const和读取值?

时间:2015-02-18 01:42:05

标签: c language-lawyer strict-aliasing

澄清:我的问题是:

  • UB是否使用int类型的左值来访问有效类型为const int的对象?

这个问题有两个代码示例,它们使用类型int的左值来访问有效类型const int的对象,我的目的是尽可能少地分散对象。如果除了这个特定问题之外还有任何其他UB来源,请发表评论,我会尝试更新代码示例。


以下是讨论的具体代码示例:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    const int c = 5;

    printf("%d\n", *(int *)&c);
}

我认为它可能是UB的原因是严格的别名规则似乎说它是UB:

  

C11 6.5 / 7

     

对象的存储值只能由具有其中一个的左值表达式访问   以下类型:

     
      
  • 与对象的有效类型兼容的类型
  •   
  • 与对象的有效类型兼容的类型的限定版本,
  •   
  • ...
  •   

对象的有效类型(6.5 / 6)这里是const int

第一个要点:intconst int不是兼容类型(6.2.7 / 1,6.7.3 / 10)。

第二个要点:int似乎不是const int的合格版本,因为我们没有通过添加限定符来生成它。但是6.2.5 / 26不清楚:

  

每个非限定类型都有几个类型的限定版本,对应于const,volatile和restrict限定符中的一个,两个或全部三个的组合。类型的限定或非限定版本是属于相同类型类别且具有相同表示和对齐要求的不同类型。派生类型不是由派生类型的限定符(如果有)限定的。

它没有定义什么是“const int”的合格版本,它只在应用于非限定类型时定义术语“限定版本”。


第二个代码示例:

int *pc = malloc(sizeof *pc);
memcpy(pc, &c, sizeof c);
printf("%d\n", *pc);   // UB?

由于memcpy保留了有效类型(6.5 / 6),因此阅读*pc与严格别名规则的完全相同,与第一个示例中的*(int *)&c读取完全相同。

1 个答案:

答案 0 :(得分:2)

不是。你发现的是为什么它不能被暗示。

[6.2.5 / 26]指出:

  

每个非限定类型都有几个类型的限定版本,对应于const,volatile和restrict限定符中的一个,两个或全部三个的组合。   类型的限定或非限定版本是属于相同类型类别且具有相同表示和对齐要求的不同类型。

(注意:每个不合格的类型。const int不合格,但int不合格。)

用脚注:

  

相同的表示和对齐要求意味着可互换性作为函数的参数,函数的返回值和联合的成员。

这意味着读取它将以相同的方式工作并产生相同的值。

[6.7.3 / 6]仅指定UB进行修改:

  

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