C++ 通过指向int的指针为char数组别名合法吗?
我知道标准中明确允许以下内容:C++ 通过指向int的指针为char数组别名合法吗?,c++,language-lawyer,strict-aliasing,C++,Language Lawyer,Strict Aliasing,我知道标准中明确允许以下内容: int n = 0; char *ptr = (char *) &n; cout << *ptr; int n=0; char*ptr=(char*)&n; cout在这里,union结构可能很有用 union类似于struct,不同之处在于union的所有元素占用相同的存储区域 换句话说,它们是“看待同一事物的不同方式”,就像FORTRAN的等价性声明一样。因此,例如: union { int foo; float bar;
int n = 0;
char *ptr = (char *) &n;
cout << *ptr;
int n=0;
char*ptr=(char*)&n;
cout在这里,union
结构可能很有用
union
类似于struct
,不同之处在于union
的所有元素占用相同的存储区域
换句话说,它们是“看待同一事物的不同方式”,就像FORTRAN的等价性声明一样。因此,例如:
union {
int foo;
float bar;
char bletch[8];
}
提供了三种完全不同的方法来考虑相同的存储区域。(联合体的存储大小是其最长组件的大小。)
foo
、bar
和bletch
都是同一存储的同义词
union
通常与typedef
一起使用,如本StackOverflow文章所示:.代码int*ptr=(int*)和存储[0]*ptr=0代码>违反严格的别名规则(C++14[basic.lval]/10),导致未定义的行为
正在访问的对象具有类型char
,但用于访问的glvalue具有类型int
char
的“对象动态类型”仍然是char
。(仅在派生类的情况下,与静态类型不同)。C++没有任何等价于C的“有效类型”,它允许类型化对象通过使用赋值操作符到Malc空间中被“创建”。
关于正确使用std::aligned_存储
,您应该使用placement new在存储中创建一个对象。使用placement new可以结束char
(或其他)对象的生存期,并创建指定类型的新对象(动态存储持续时间),重新使用相同的存储。这样就不会有严格的别名冲突
您可以对char数组执行相同的操作,例如:
alignas(int) char storage[sizeof(int)];
int *ptr = new(storage) int;
*ptr = 0;
cout << *ptr;
alignas(int)字符存储[sizeof(int)];
int*ptr=新(存储)int;
*ptr=0;
库特
写入int,因此它是对int的访问,具有int类型的左值,因此部分代码可以
演员阵容在道德上是好的,但是C/C++标准文本没有清楚地描述演员阵容、指针或任何基本内容。投否决票的人可以留下评论吗?我不知道你是否可以这样做,但标准定义了以你尝试的方式访问a中的变量,我没有投票,但是,如果你要求参考标准,我希望你展示你自己的研究,引用你认为相关的部分,并描述你自己不确定的结论。@chbaker0查看我上面给出的链接,它看起来像是一个示例实现(希望符合标准)做与你现在做的几乎相同的事情here@user2079303好的,我将在我的研究中添加一个让我感到矛盾的问题:C++中有这个问题,根据这个规则在C++中是不合法的(但是它是C)。这个词是相同的。C++不允许通过联合进行类型双关。您只能读取最近分配给成员的内容。哦,foo。。。你是多么正确。。。我很难过*(…(“键入双关语”…不知何故,我以前从未听说过这个词。但是,我喜欢它。)@M.M“您只能读出最近分配给成员的内容”这也不是真的。第二部分是我误解的核心;我没有意识到对象类型是通过使用placementnew
建立的。因此这意味着使用malloc
然后将结果内存用作int
或char
以外的任何其他原语也是未定义的少做placement new?@chbaker0是的,这不是很广为人知;省略placement new和执行严格的别名冲突似乎最有效(或全部有效)大多数时候,很多人只是这样做,要么不知道问题所在,要么不关心标准。根据标准-这是正确的,在写入malloc空间之前,必须在malloc空间上使用新的位置。@curiousguy标准不支持你的说法。说声明字符数组使一个无限多的对象。这个线程是关于标准实际上说了什么,而不是你希望它说什么。他们确实清楚地描述了它,你只是似乎不同意标准所说的含义,所以你假装它没有说。@M.M“他们确实清楚地描述了它”我很高兴了解到这一点。请查看并回答我关于指针的许多问题:@M.M这里的含义是,直到最近,对联合的任何使用都是未定义的,这是非常愚蠢的。
alignas(int) char storage[sizeof(int)];
int *ptr = new(storage) int;
*ptr = 0;
cout << *ptr;
*ptr = 0;