#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct person {
    char *name;
    unsigned int age;
    unsigned int height;
    unsigned int weight; 
} person_t;

int main() {
   
    void *p;
    person_t *p1;
    p = malloc(sizeof(person_t));
    p1 = (person_t *)p;

    p1->name = malloc(80*sizeof(char));
    strcpy(p1->name,"my_name"); //edited after rightly pointing in comments
    p1->age=25; p1->height=6; p1->weight=65;

    printf("\n%p -> %u == ",(p+12),*(unsigned int *)(p+12)) ;
    printf("%p -> %u",&p1->height,p1->height) ;

    return 0;
}

输出:

0x16c46b4 -> 6 == 0x16c46b4 -> 6

两个打印件都打印相同的指针和值.有人可以帮助我更清楚地理解它吗?

执行了上述代码并了解到两个打印中预期相同的o/p,但仍然没有清楚地说明.

推荐答案

您的代码不可移植,因为它依赖于一些实现细节.

您正在使用一个系统,其中int似乎有32位,指针有64位大. struct 中也没有填充.至少前3个元素之间没有填充. 最后,您在GCC中使用一个非标准扩展,将void*视为char*.

这意味着,该 struct 的内存布局看起来像这样:

+--------+------------+--------+
| offset |  field     |  size  |
+--------+------------+--------+
|   0    | char *name |    8   |
+--------+------------+--------+
|   8    | uint age   |    4   |
+--------+------------+--------+
|  12    | uint height|    4   |
+--------+------------+--------+
|  16    | uint weight|    4   |
+--------+------------+--------+

这意味着,如果您获取该 struct 体的地址并添加12个字节,您将获得height个成员的地址. 您可以通过打印offsetof(person_t, height)来验证这一点.

如果您执行&p1->height,编译器就会为您进行计算.

如果执行p+12,则手动进行计算并得到相同的结果. 这依赖于允许使用void*进行计算的海湾合作委员会扩展.它的效果与char*相同,这意味着指针算术添加单个字节.

C++相关问答推荐

C中出现分段错误后关闭文件

Malloc(sizeof(char[Length]))是否不正确?

GCC预处理宏和#杂注GCC展开

变量>;-1如何在C中准确求值?

在一个小型玩具项目中实现终端历史记录功能

当我更改编译优化时,相同的C代码以不同的方式运行

对重叠字符串使用MemMove

如何在STM8项目中导入STM8S/A标准外设库(ST VisualDeveloper)?

每次除以或乘以整数都会得到0.0000

变量的作用域是否在C中的循环未定义行为或实现定义行为的参数中初始化?

为什么二进制文件的大小不会随着静态数据的大小而增加?

Fscanf打印除退出C代码为1的程序外的所有内容

try 查找带有指针的数组的最小值和最大值

是否有单独的缓冲区用于读写库调用?

我编写这段代码是为了判断一个数字是质数、阿姆斯特朗还是完全数,但由于某种原因,当我使用大数时,它不会打印出来

';malloc():损坏的顶部大小';分配超过20万整数后

当 n 是我们从用户那里获得的整数时,创建 n 个 struct 参数

可以从指针数组中的值初始化指针吗?

nullptr_t 是否会 destruct 类型双关或指针转换?

将帧从相机 (/dev/video0) 复制到帧缓冲区 (/dev/fb0) 会产生意外结果