想了解结构体指针和void指针转换

问题描述 投票:0回答:1
#include <stdio.h>
#include <stdlib.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));
    p1->name = "my_name";
    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,但仍然不方便清楚。

c pointers struct
1个回答
0
投票

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

您正在使用一个系统,其中

int
似乎有 32 位,而指针有 64 位大。 您的结构中也没有填充。 最后,您在 GCC 中使用非标准扩展,将
void*
视为
char*

这意味着,该结构的内存布局如下所示:

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

这意味着,如果您获取该结构体的地址并添加 12 个字节,您将获得

height
成员的地址。 您可以通过打印
offsetof(person_t, height)
来验证这一点。

如果您这样做

&p1->height
,编译器会为您进行计算。

如果您这样做

p+12
,您可以手动进行计算并得到相同的结果。 这依赖于允许使用
void*
进行计算的 GCC 扩展。它的作用与
char*
相同,这意味着指针算术添加单个字节。

© www.soinside.com 2019 - 2024. All rights reserved.