【发布时间】:2021-01-08 00:58:34
【问题描述】:
我有一项任务让我浪费了宝贵的时间却一无所获。我必须从作为 void *c 传递给函数的结构中读取内容。我可以毫无问题地读取它的内容,除了指向另一个结构的指针的字段。示例代码:
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct Car Car;
struct Car {
int year;
int type;
int free;
struct {
char *name;
char *city;
} *facility;
};
int main()
{
Car *c = malloc(sizeof(Car)*2);
c->year = 2020;
c->type = 2;
c->free = 1;
c->facility = malloc(200);
c->facility->name = malloc(10);
c->facility->city = malloc(10);
snprintf(c->facility->name, 5, "Test");
snprintf(c->facility->city, 5, "Test");
test(c);
}
int test(void *c)
{
int year = *(void **) c;
int type = *(void **) (c+4);
int free = *(void **) (c+4+4);
printf("Year %d\n",year);
printf("Type %d\n",type);
printf("Free %d\n",free);
void *facility;
facility = *(void **) (c+4+4+4);
printf("Facility name %s", *(void **) facility);
printf("Facility city %s", *(void **) facility+8);
}
我无法阅读的部分是设施名称和设施城市。我知道我可以使用 -> 轻松访问,但作业要求准确理解内存中的结构是如何定义的,并使用 void* 直接提取其内容。谢谢。
【问题讨论】:
-
c+4这已经是非法的了,例如见Pointer arithmetic for void pointer in C。 -
为什么c+4是非法的?您的链接说是非法的,因为它是不完整的类型,但在这种情况下它不是,那么就不是非法的。尤金,不工作。我正在尝试读取存储在 Car 中的指针,然后读取存储在那里的 char *,因为前一个指针而递增 8,然后读取下一个 char * 即城市。感谢您投反对票...
-
@Ivan 这是非法的,因为
c被声明为void *并且指针算术(递增、加法等)对于 void 指针是非法的。想一想,当你有一个int *p;时,p + 1指向下一个int。指针的值实际上增加了sizeof int,这是int占用的字节数。但是当你有一个void *p;时,你不知道p指向什么,也不知道something 有多大,所以谈论p + 1是没有意义的。仅仅因为 gcc 长期以来一直将其作为扩展并不能使其合法 C,从来没有。附言顺便说一句,这不是我的反对意见。 -
@Ivan
increase by 4 (int) or 8 (pointer)我的意思是,c + 4只是碰巧“工作”,因为您似乎甚至不知道您正在使用的编译器扩展。该代码可能会在其他编译器中给出虚假结果,或者根本无法编译。正确/便携的写法是(char *)c + sizeof(int)。 -
@dxiv:添加到
void *是 C 标准定义为 conforming(比 strictly conforming 更大的集合)。 C 标准没有定义行为,但也没有使其非法。
标签: c memory struct structure void-pointers