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_Pointers_Struct - Fatal编程技术网

C结构指针后面的内存内容

C结构指针后面的内存内容,c,pointers,struct,C,Pointers,Struct,浏览一些旧的C代码,我发现了这个代码片段。我完全搞不清楚幕后发生了什么 我对结构指针的用法和可操作性没有完全的了解,我也不能完全理解在下面的代码中内存是如何存储和访问的 struct x{ int i1; int i2; char ch1[8]; char ch2[8]; }; struct y{ long long int f1; char f2[18]; }; int main(void) { struct x * myX; struct y * myY; myX = malloc(si

浏览一些旧的C代码,我发现了这个代码片段。我完全搞不清楚幕后发生了什么

我对结构指针的用法和可操作性没有完全的了解,我也不能完全理解在下面的代码中内存是如何存储和访问的

struct x{
int i1;
int i2;
char ch1[8];
char ch2[8];
};

struct y{
long long int f1;
char f2[18];
};

int main(void)
{
struct x * myX;
struct y * myY;
myX = malloc(sizeof(struct x));
myX->i1 = 4096;
myX->i2 = 4096;
strcpy(myX->ch1,"Stephen ");
strcpy(myX->ch2,"Goddard");
myY = (struct y *) myX;
printf("myY->f1 = %d\n", myY->f1);
printf("myY->f2 = %s\n", myY->f2);
}
这个输出

 myY->f1 = 4096
 myY->f2 = Stephen Goddard
强制转换后,
i1
存储在
myY->f1
中,ch1和ch2都存储在
myY->f2
中。我的问题是怎么做?。演员阵容结束后,记忆内容是什么样子的

我知道这与结构的大小和指针指向的位置有关(很明显),但是在看了这段代码之后,它肯定让我意识到我对指针缺乏理解


谢谢

演员阵容不会影响记忆。强制转换只是将一个对象视为另一个不同类型的对象。如果愿意,可以将代码想象为有一个
联合{struct x a;struct y b;}
,然后写入
a
,但从
b
读取

这是一种未定义的行为,但碰巧出现的情况是,各种对象相互重叠,因此您可以看到观察到的结果


第一个
strcpy(myX->ch1,“Stephen”)
也是未定义的行为,因为缓冲区对于字符串来说太小。

我在这里假设为32位
int
struct x
后面的内存有24个字节,布局如下:

Bit   0000 0000 00111111 11112222
      0123 4567 89012345 67890123
      ----|----|--------|--------
Field  i1   i2     ch1      ch2
下面是在第一个strcpy之后发生的情况:

      ----|----|--------|--------
Field  i1   i2     ch1      ch2
      ----|----|--------|--------
                Stephen \0
                         ^
                         |
                  Zero terminator
      ----|----|--------|--------
Field  i1   i2     ch1      ch2
      ----|----|--------|--------
                Stephen  Goddard\0
                                 ^
                                 |
                           Zero terminator
Bit   00000000 001111111111222222
      01234567 890123456789012345
      --------|------------------
Field     f1            f2
下面是第二个strcpy之后发生的情况:

      ----|----|--------|--------
Field  i1   i2     ch1      ch2
      ----|----|--------|--------
                Stephen \0
                         ^
                         |
                  Zero terminator
      ----|----|--------|--------
Field  i1   i2     ch1      ch2
      ----|----|--------|--------
                Stephen  Goddard\0
                                 ^
                                 |
                           Zero terminator
Bit   00000000 001111111111222222
      01234567 890123456789012345
      --------|------------------
Field     f1            f2
注意第一个strcpy的终止零是如何被写入以完成字符串的

以下是结构y的布局图:

Bit   00000000 001111111111222222
      01234567 890123456789012345
      --------|------------------
Field     f1            f2
当您将
struct x
指针投射到
struct y
时,您不会复制任何内容。
struct y
的布局与
struct x
的布局像饼干切割器一样对齐,然后通过
f2
窗口获取组合的
x.ch1
x.ch2
的内容:


就打印
4096
而言,这是未定义的行为:您正在将
f1
类型为
long-long-int
printf
传递到
int
参数位置的
printf
,因此
printf
将数据重新解释为
int
,切断上半部分(未定义的行为)。如果使用适当的格式说明符,得到的数字是
17592186048512

至于内存,它仍然只保存最初
malloc
ed的
struct x
中的值,加上两个指针
myX
myY
,它们都指向
struct x

然而,
ch1
f2
恰好从相同的相对内存索引8开始(显然,
i1
f1
也从索引0开始),并且
f2
也与
ch2
重叠,因此您得到:

                      i1    i2    ch1               ch2
from x's perspective: [int] [int] [char] [char] ... [char] ...
from y's perspective: [long long] [char] [char] ... [char] ...
                      f1          f2
                      0     4     8      9          16

这是因为一个
long-long
长度等于两个
int
s,即8个字节。

第一个
strcpy
调用调用未定义的行为,因为它覆盖了一个不存在的数组元素,即
ch1[8]
。我想我真正的问题是,在转换之后,myY->f2现在如何包含myX->ch1和ch2?@ElliotM:
y
结构的
f2
子对象与
x
结构的
ch1
子对象位于同一内存位置;第一个空终止符被第二个strcpy覆盖(注意缓冲区溢出)。为什么f1只存储4096而不是40964096?@ElliotM实际上,它存储
17592186048512
。但是,您的程序告诉printf它是一个
int
,因此
%d
去掉其他四个字节。