Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 转换不完整的结构指针是否为未定义行为?_C_Language Lawyer_C11_Strict Aliasing - Fatal编程技术网

C 转换不完整的结构指针是否为未定义行为?

C 转换不完整的结构指针是否为未定义行为?,c,language-lawyer,c11,strict-aliasing,C,Language Lawyer,C11,Strict Aliasing,我目前正在阅读一些严格的别名规则,我想知道将指针强制转换到不完整的结构是否是未定义的行为 示例1: #include <stdlib.h> struct abc; int main(int argc, char *argv[]) { struct abc *mystruct; char *buf; buf = malloc(100); mystruct = (struct abc*)buf; // and then mystruct could be su

我目前正在阅读一些严格的别名规则,我想知道将指针强制转换到不完整的结构是否是未定义的行为

示例1

#include <stdlib.h>

struct abc;

int main(int argc, char *argv[])
{
  struct abc *mystruct;
  char *buf;

  buf = malloc(100);
  mystruct = (struct abc*)buf;

  // and then mystruct could be submitted to a function, where it is
  // casted back to a "char *", the "struct abc" will never be completed.

  return 0;
}
struct abc1;
struct abc2;

int foo(struct abc1 *mystruct1)
{
  struct abc2 *mystruct2;

  mystruct2 = (struct abc2 *)mystruct1;

  // and then mystruct2 could be submitted to a function, where it is
  // casted to a "char *", both structs stay incomplete.

  return 0;
}

那么,我的问题是:像c11标准禁止的两个示例中那样,是否将指针强制转换为不完整的结构,如果是,标准的哪个部分禁止它?

标准的一个关键相关部分是c11:

28指向void的指针应与指向字符类型的指针具有相同的表示和对齐要求。48)同样,指向兼容类型的合格或不合格版本的指针应具有相同的表示和对齐要求。指向结构类型的所有指针应具有彼此相同的表示和对齐要求。所有指向联合类型的指针应具有彼此相同的表示和对齐要求。指向其他类型的指针不需要具有相同的表示或对齐要求

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

另一个问题尤其是:

7指向对象类型的指针可以转换为指向不同对象类型的指针。如果所引用类型的结果指针未正确对齐(68),则行为未定义。否则,当再次转换回时,结果应与原始指针进行比较。当指向对象的指针转换为指向字符类型的指针时,结果将指向对象的最低寻址字节。结果的连续增量(直到对象的大小)产生指向对象剩余字节的指针

68)通常,“正确对齐”的概念是可传递的:如果类型a的指针与类型B的指针正确对齐,而类型B的指针又与类型C的指针正确对齐,则类型a的指针与类型C的指针正确对齐


因此,我的理解是,问题中显示的两个示例代码片段都没有问题。结构类型不完整,但这对于所示的操作来说不是问题。代码的“and then”部分不一定有问题,这取决于实际存在的内容。

在指向结构类型的指针之间转换本身就可以了。问题是你以后具体如何处理这些指针。一个更完整的示例会有所帮助。@dbush将结构指针转换回
char*
是以后唯一要做的事情。然后读取并修改
字符*
。结构永远不会完整。但是,我读到,有两个不兼容的类型指向同一个对象可能是无效的,这是错误的吗?如果您通过指向另一个类型(而不是
char*
)的指针读取一个类型的对象,则会出现严格的别名。我看这里不会发生这种事,谢谢!如果对象被分配给不精确重叠的对象或类型不兼容的完全重叠的对象,
又如何呢?提供的示例是否不受此影响?示例中唯一的对象是指针(指向不完整的结构类型)。所有的作业都是洁净的;没有不精确的重叠对象,类型也不是不兼容的——尽管标准中有这一部分(是其中一个更难理解的。它定义的一件事是,可以使用具有相同类型文本的单独翻译单元来创建代码,这些代码可以链接在一起,形成一个连贯的程序。我认为§6.7¨4或UB在这里不适用。我试图理解句子
所有指向结构类型的指针都应彼此具有相同的表示和对齐要求,但我正在努力。请您详细解释一下好吗?这是否意味着我的程序中指向许多不同结构的所有指针都具有相同的地址对齐方式?如果是,对齐值是多少?相同表示法的含义是什么?@user2162550:哎哟-好问题,复杂答案。首先,这意味着所有指向结构的指针大小相同,而不管结构类型如何。因此,
sizeof(struct Foo*)==sizeof(struct Bar*)
与如何(或即使是)无关结构体是定义的。其次,这意味着如果一个
struct Foo*
需要在8字节边界上对齐,那么
struct Bar*
也需要对齐。“相同表示”要求对机器(大型机)施加条件这曾经存在,但现在主要是博物馆的作品-它们可能不如你的手机强大。[…继续…][…继续…]一些大型机有复杂的硬件描述符,用于检查指针是否被滥用。“同一表示”规则是指这些机器不能反对将
struct Foo*
转换为
struct Bar*
或反之亦然。我不确定是否允许它们投诉n如果您使用转换后的指针访问错误的类型。但是,现在很少在字段中找到此类计算机。请参阅Wikipedia上的示例(3 mips;8 MiB内存)。