- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
假设代码使用 c11 编译并启用严格别名。
我不是在寻找不同的方法,我想专注于这个特定问题,以及它是否有效或为什么无效。
(如果我无意中犯了一些不相关的错误,请告诉我,我会修复)
c11 标准说:
6.2.5.28 All pointers to structure types shall have the same representation and alignment requirements as each other.
6.7.2.1.6 a structure is a type consisting of a sequence of members, whose storage is allocated in an ordered sequence
这意味着结构 A 和 B 中指针的大小和对齐方式相同。
#include <stdio.h>
#include <stdlib.h>
struct S1
{
int i ;
} ;
struct S2
{
float f ;
} ;
struct A
{
struct S1* p ;
} ;
struct B
{
struct S2* p ;
} ;
int main( void )
{
结构 A 和 B 有指向结构 S1 和 S2 的指针,结构 A 和 B 保证具有相同的大小和对齐方式。
我们有一个 struct B
,它的成员指针是一个 struct S2 指针,但指向某个 struct S1,这是通过 void* 转换实现的。
struct S1 s1 = { 0 } ;
struct B* b = malloc( sizeof( *b ) ) ;
b->p = ( void* ) &s1 ;
没关系,我们可以存储指针,只要我们不实际使用指针即可。但我们想要。我们可以将指针转换为结构 S1。
( ( struct S1* )(b->p) )->i = 123 ; //redundant brackets for emphasis
printf("%d\n" , s1.i ) ;
并正确使用它。
到目前为止,我没有发现任何问题,因为指针已转换为正确的类型。
但是我们可以将整个结构 B 转换为结构 A 吗?它们在大小和对齐方面是相同的,尽管标准可能会提示(?),编译器会产生未定义的行为吗?
( ( struct A* )b)->p->i = 666 ;
printf("%d\n" , s1.i ) ;
我知道解决方案是使用 union (或使用 void 并随时正确转换),因为标准允许使用上次未使用的成员来存储值。
6.5.2.3.3( 95 ) If the member used to read the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called "type punning"). This might be a trap representation.
但是,我想避免这种情况:
struct C
{
union
{
struct S1* p1 ;
struct S2* p2 ;
} ;
} ;
struct C* c = malloc( sizeof( *c ) ) ;
c->p2 = ( void* )&s1 ;
c->p1->i = 444 ;
printf("%d\n" , s1.i ) ;
return 0 ;
}
最佳答案
到目前为止您所描述的内容:
But can we cast the whole struct B to struct A instead?
都是正确的,但不幸的是这个问题的答案是否 如果两个结构包含“公共(public)初始序列”,则只允许通过指向不兼容类型的指针访问结构,一世。 e.如果他们的前几个成员具有相同的类型。由于您的结构没有(即,第一个成员属于不同类型),因此通过指向 S2
的指针访问 S1
类型的对象是不合法的,反之亦然反之亦然。特别是,这样做违反了 strict aliasing rule .
来自 C99,6.5.7:
An object shall have its stored value accessed only by an lvalue expression that has one of the following types:76)
— a type compatible with the effective type of the object,
— a qualified version of a type compatible with the effective type of the object,
— a type that is the signed or unsigned type corresponding to the effective type of the object,
— a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
— an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
— a character type.
关于转换结构指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21650839/
我刚接触 C 语言几周,所以对它还很陌生。 我见过这样的事情 * (variable-name) = -* (variable-name) 在讲义中,但它到底会做什么?它会否定所指向的值吗? 最佳答案
我有一个指向内存地址的void 指针。然后,我做 int 指针 = void 指针 float 指针 = void 指针 然后,取消引用它们以获取值。 { int x = 25; vo
我正在与计算机控制的泵进行一些串行端口通信,我用来通信的 createfile 函数需要将 com 端口名称解析为 wchar_t 指针。 我也在使用 QT 创建一个表单并获取 com 端口名称作为
#include "stdio.h" #include "malloc.h" int main() { char*x=(char*)malloc(1024); *(x+2)=3; --
#include #include main() { int an_int; void *void_pointer = &an_int; double *double_ptr = void
对于每个时间步长,我都有一个二维矩阵 a[ix][iz],ix 从 0 到 nx-1 和 iz 从 0 到 nz-1。 为了组装所有时间步长的矩阵,我定义了一个长度为 nx*nz*nt 的 3D 指针
我有一个函数,它接受一个指向 char ** 的指针并用字符串填充它(我猜是一个字符串数组)。 *list_of_strings* 在函数内部分配内存。 char * *list_of_strings
我试图了解当涉及到字符和字符串时,内存分配是如何工作的。 我知道声明的数组的名称就像指向数组第一个元素的指针,但该数组将驻留在内存的堆栈中。 另一方面,当我们想要使用内存堆时,我们使用 malloc,
我有一个 C 语言的 .DLL 文件。该 DLL 中所有函数所需的主要结构具有以下形式。 typedef struct { char *snsAccessID; char *
我得到了以下数组: let arr = [ { children: [ { children: [], current: tru
#include int main(void) { int i; int *ptr = (int *) malloc(5 * sizeof(int)); for (i=0;
我正在编写一个程序,它接受一个三位数整数并将其分成两个整数。 224 将变为 220 和 4。 114 将变为 110 和 4。 基本上,您可以使用模数来完成。我写了我认为应该工作的东西,编译器一直说
好吧,我对 C++ 很陌生,我确定这个问题已经在某个地方得到了回答,而且也很简单,但我似乎找不到答案.... 我有一个自定义数组类,我将其用作练习来尝试了解其工作原理,其定义如下: 标题: class
1) this 指针与其他指针有何不同?据我了解,指针指向堆中的内存。如果有指向它们的指针,这是否意味着对象总是在堆中构造? 2)我们可以在 move 构造函数或 move 赋值中窃取this指针吗?
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: C : pointer to struct in the struct definition 在我的初学者类
我有两个指向指针的结构指针 typedef struct Square { ... ... }Square; Square **s1; //Representing 2D array of say,
变量在内存中是如何定位的?我有这个代码 int w=1; int x=1; int y=1; int z=1; int main(int argc, char** argv) { printf
#include #include main() { char *q[]={"black","white","red"}; printf("%s",*q+3); getch()
我在“C”类中有以下函数 class C { template void Func1(int x); template void Func2(int x); }; template void
我在64位linux下使用c++,编译器(g++)也是64位的。当我打印某个变量的地址时,例如一个整数,它应该打印一个 64 位整数,但实际上它打印了一个 48 位整数。 int i; cout <<
我是一名优秀的程序员,十分优秀!