我最初问的是这个问题:Type Punning with Unions and Heap
又不想让问题继续发展到将来任何人都不知道原始问题是什么的程度,我有一个副题。
阅读本网站后: https://kristerw.blogspot.com/2016/05/type-based-aliasing-in-c.html
在底部附近讨论了malloc的内存。可以肯定地说,当堆中有内存时,从一种指针类型转换为另一种指针类型是安全的吗?
示例:
#include <stdio.h>
#include <stdlib.h>
struct test1
{
int a;
char b;
};
struct test2
{
int c;
char d;
};
void printer(const struct test2* value);
int main()
{
struct test1* aQuickTest = malloc(sizeof(struct test1));
aQuickTest->a = 42;
aQuickTest->b = 'a';
printer((struct test2*)aQuickTest); //safe because memory was malloc'd???
return 0;
}
void printer(const struct test2* value)
{
printf("Int: %i Char: %c",value->c, value->d);
}
猜测可能并不安全。用memcpy执行此操作的正确方法是什么?我将尝试编写一个示例,其中包含希望能起作用的功能?
struct test2* converter(struct test1* original);
int main()
{
struct test1* aQuickTest = malloc(sizeof(struct test1));
aQuickTest->a = 42;
aQuickTest->b = 'a';
struct test2* newStruct = converter(aQuickTest);
printer(newStruct);
return 0;
}
struct test2* converter(struct test1* original)
{
struct test2* temp;
memcpy(&temp, &original, sizeof(struct test2));
return temp;
}
答案 0 :(得分:3)
void *pnt = malloc(sizeof(struct test1));
pnt指针后面的存储器有什么类型?没有类型它是未初始化的(其值为“不确定”)。只有“记忆”。
然后您这样做:
struct test1* aQuickTest = malloc(sizeof(struct test1));
您只投下了指针。这里什么都没有发生。没有生成程序集。读取未初始化的内存是未定义的行为,因此您无法从aQuickTest->a
进行读取(尚未)。但是您可以分配:
aQuickTest->a = 1;
这将写入内存中的对象struct test1
。这是作业。您现在可以阅读aQuickTest->a
,即。打印。
但是以下
printf("%d", ((struct test2*)aQuickTest)->a);
是未定义的行为(尽管它将/应该起作用)。您使用不匹配的指针类型struct test1
访问基础对象(即struct test2*
)。这称为“严格别名违反”。使用非compatible type的句柄取消引用对象(即执行->
或*
)会导致未定义的行为。 struct test1
和struct test2
“看起来相同”并不重要。它们是不同的类型。规则在C11 standard 6.5p7中。
在第一个代码中,在printf("Int: %i Char: %c",value->c
内部发生了未定义的行为。访问value->
使用不兼容的句柄访问基础内存。
在第二段代码中,变量 无论如何: 访问 temp
仅是一个指针。 original
也是一个指针。进行memcpy(&temp, &original, sizeof(struct test2));
是无效的,因为&temp
写入temp
指针,而&original
写入original pointer. No to the memory behind pointers. As you write out of bounds into
&temp pointer and read of bounds from
&original pointer (because most probably
sizeof(temp) struct test1* original = &(some valid struct test1 object).
struct test2 temp;
memcpy(&temp, original, sizeof(struct test2));
printf("%d", temp.a); // undefined behavior
temp
变量后面的内存仍然无效。由于original
没有struct test2
对象,因此它仍然无效。 memcpy
不会更改内存中对象的类型。