当前位置: 首页 > 知识库问答 >
问题:

将指向同一联合成员的两个指针传递给函数是否违反了严格的别名规则?[重复]

董高逸
2023-03-14

注意:学习严格的别名规则。请耐心等待。

代码示例(t935.c):

#include <stdio.h>

int f(int* pi, double* pd)
{
    *pi = 13;
    *pd = 7E-323;
    return *pi;
}

int main(void)
{
    union { int i; double d; } u;
    printf("%d\n", f(&u.i, &u.d));
    return 0;
}

调用:

$ gcc t935.c -Wall -Wextra -std=c11 -pedantic  && ./a.exe
14

$ gcc t935.c -Wall -Wextra -std=c11 -pedantic -O2 && ./a.exe
13

$ gcc t935.c -Wall -Wextra -std=c11 -pedantic -O2 -fno-strict-aliasing && ./a.exe
14

问题:向函数传递指向同一联合成员的两个指针是否违反了严格的别名规则?

这个问题源于工会和类型双关语。

更新20210901

如果union类型在全局范围内定义,会发生什么?

对于“联合u在全局范围内定义”(实际上是文件范围)的情况,gcc和clang都显示出与上面报告的gcc相同的结果。

共有1个答案

程正阳
2023-03-14

这是C标准中的缺陷。请参阅缺陷报告236。

6.5 7中的混淆现象规则旨在允许编译器假设指向不满足规则的两种类型的指针指的是“不同的”对象,但该规则未能充分提供联合成员(根据缺陷报告,动态分配内存中的对象也是如此)。获取两个联合成员的地址可能会产生指向两种类型的指针,根据混淆现象规则,这两种类型可能不是别名,但指的是相同的内存。因此,C标准在这方面被打破了,C委员会也没有纠正这个问题。

 类似资料:
  • 我编写了一个代码来传递函数指针列表(按其名称)作为参数。但我有错误。你能解释为什么我在做地图时有错误吗? 错误: 34:18:错误:无法将'void(Bar::)(int, int)'转换为'std::map, void(*)(int, int) 35:18:错误:无法将“无效(foo::)(整数,整数)”转换为“标准::映射,无效(*)(整数,整型) 41:70:错误:没有用于调用“std::v

  • 示例代码: 我认为这是常见的,被认为是可以接受的。该标准确实保证结构中没有初始填充。但是,这种情况未在严格别名规则中列出(C 17 [basic.lval]/11): 如果程序尝试通过下列类型之一以外的 gl 值访问对象的存储值,则行为未定义: (11.1)物体的动态类型, (11.2) 对象的动态类型的 cv 限定版本, (11.3) 与对象的动态类型相似的类型(如 7.5 中所定义), (11

  • 在第4.9小节,我们已经知道,切片实际是一个指向潜在数组的指针。我们常常需要把切片作为一个参数传递给函数是因为:实际就是传递一个指向变量的指针,在函数内可以改变这个变量,而不是传递数据的拷贝。 因此应该这样做: func findBiggest( listOfNumbers []int ) int {} 而不是: func findBiggest( listOfNumbers *[]i

  • 我正在学习如何在C中使用并写了以下示例: 问:是否保证在所有情况下指向一个结构的指针都是指向它的第一个元素的完全相同的指针? 在这种特殊的情况下,它能像我预期的那样工作,但我不确定它是否能得到保证。编译器可以在开始时插入一些填充吗? 我唯一能找到的关于结构类型布局的是N1570的类型: 结构类型描述了一组按顺序分配的非空成员对象(在某些情况下,还包括一个不完整的数组),每个对象都有一个可选的指定名

  • C++ 指针 C++ 允许您传递指针给函数,只需要简单地声明函数参数为指针类型即可。 下面的实例中,我们传递一个无符号的 long 型指针给函数,并在函数内改变这个值: #include <iostream> #include <ctime> using namespace std; void getSeconds(unsigned long *par); int main () {

  • 我正在阅读关于reinterpret_cast的笔记,它是混淆现象(http://en.cppreference.com/w/cpp/language/reinterpret_cast)。 我写了代码: 我认为这些规则在这里不适用: T2是对象的(可能是cv限定的)动态类型 T2和T1都是指向相同类型T3的指针(可能是多级的,可能在每个级别都是cv限定的)(因为C11) T2是一个聚合类型或并集类