C 为什么要从从void初始化的结构中获取垃圾值**
我测试这段代码:C 为什么要从从void初始化的结构中获取垃圾值**,c,pointers,memory-management,data-structures,C,Pointers,Memory Management,Data Structures,我测试这段代码: void foo (void* data[]) { static struct structure { char character; int integer; } st1 = *((struct structure *)data); printf("[%i][%c]", st1.integer, st1.character); } int main (void) { void* *data = ca
void foo (void* data[])
{
static struct structure
{
char character;
int integer;
} st1 = *((struct structure *)data);
printf("[%i][%c]", st1.integer, st1.character);
}
int main (void)
{
void* *data = calloc(2, sizeof(void* ));
char arg1 = 'b';
int arg2 = 20;
data[0] = (char* )&arg1;
data[1] = (int* ) &arg2;
foo(data);
return(0);
}
但我得到的是垃圾值,而不是预期值
[20] [乙]
我尝试过很多东西,包括st1=
*((struct structure*)和data)
,(尽管AFAIKdata
已经是一个地址)声明并初始化单独的结构指针,然后将其解除引用,但没有任何效果
发生这种情况的原因是什么?我应该如何正确地接近获取函数参数的相同想法?通常,可移植的情况下,您不能期望您的结构与两个
void*
的大小相同
不能期望在结构本身内部有任何特定的填充。当内存区域被重新解释为结构的一部分时,您不能期望将char
强制转换为void*
将产生相同的有效char
(我想我读过的代码)的行为是无法定义的
我最初完全忽略了这样一个事实,即您将地址分配给两个
void*
(假设您将char
和int
本身转换为void*
),因此您对这些值的重新解释根本不需要产生您所期望的结果。事实上,它可能会导致陷阱值。因此,您的代码是未定义的行为。您的问题在于您的结构本身
在您的数据
中,您在main中编写了一个int*
和一个char*
。但是,在函数中,您定义结构,因为它包含char
和int
,您应该编写以下内容:
void foo (void* data[])
{
static struct structure
{
char* character;
int* integer;
} st1 = *((struct structure *)data);
printf("[%i][%c]", *(st1.integer), *(st1.character));
}
这闻起来像UB,但你把参数的顺序搞混了。@StoryTeller很抱歉,这似乎是写博文的错,因为我既不能也不能复制/粘贴。原始代码具有适当的顺序。问题仍然存在。当我看到一个空指针时,我想——一个人在想什么——设计和编码是错误的。大错特错。修复设计和代码,使其不使用void。您的代码在多个级别上未定义。没有合理的方法“修复”此问题。
void*
在无法假定类型时使用,也无所谓。你的代码想要假设,这对它来说非常重要。结构的大小是8字节,void**的大小是12字节。两个void*将是24@Malina-除了计算错误之外,除了char
之外,对于任何数据类型,您都不能期望任何特定的sizeof
。你不需要假设,使你的代码不被定义。我只是告诉你sizeof的结果。我没有做任何计算。你能告诉我做这件事的正确方法吗?因此,我可以完成对“过于宽泛的问题”使用堆栈溢出的操作。sizeof(void**)==2
并不意味着2*sizeof(void*)==24
。这两种类型不需要大小相同。即使这些是结果。您是否认为您的结构完全位于您传递的内存的前8个字节内有问题?@Malina-正确的方法是避免这堆未定义的行为。除了无符号字符*
之外,不要处理任何原始内存。使用memcpy
或memove
并实际服用药物,从代码库中删除该黑客行为。