我昨天在大学接受了这个问题/作业。它是这样的:
Give the following structure:
typedef struct _rect {
int width;
int height;
} rect;
How could you scale the width and height members using a cast to int* without explicitly accessing the two members?
所以基本上,鉴于结构,我该怎么做
rect *my_rectangle = malloc(sizeof(rect));
my_rectangle->width = 4;
my_rectangle->height = 6;
// Change this part
my_rectangle->width /= 2;
my_rectangle->height /= 2;
使用强制转换为int或int *?
答案 0 :(得分:4)
您只能可靠地扩展第一个成员:
*((int *) my_rectangle) /= 2;
这不违反严格别名规则,因为标准明确允许将指向struct对象的指针转换为其第一个成员的指针。
C11§6.7.2.1/ 15结构和联合说明符
在结构对象中,非位字段成员和单位 哪些位字段驻留的地址按顺序增加 他们被宣布。适当地指向结构对象的指针 转换后,指向其初始成员(或者如果该成员是 位字段,然后到它所在的单元,反之亦然。 结构对象中可能有未命名的填充,但不在其中 开始。
假设这些成员之间没有填充,第二个成员也可以缩放,只要指针与成员具有相同(兼容)类型,即int
。 / p>
答案 1 :(得分:1)
他们试图教你的是这个结构如何在记忆中表现出来。它有两个int成员,所以在内存中它也可能被视为一个int数组。所以以下内容可能会奏效。
rect *my_rectangle = malloc(sizeof(rect));
my_rectangle->width = 4;
my_rectangle->height = 6;
int *my_array=(int *) my_rectangle;
my_array[0] /= 2;
my_array[1] /= 2;
但这是一个非常糟糕的黑客攻击,编译器完全有可能以完全不同的方式存储你的结构,这样将它转换为int *
就不会产生预期的效果。所以如果你想写好干净的可移植代码恕我直言,那就完全不推荐了。
如果有人要更改结构,例如通过制作宽度&高度为float
而不是int
,代码可能会在没有任何问题或警告的情况下进行编译,然后根本无法满足您的预期。
答案 2 :(得分:1)
您有结构的起始地址,因此您可以访问各个元素 通过相应地递增地址。这里因为两个类型都是int,所以你可以更好地使用整数指针来使用char指针。
bannerAd?.isHidden = true
答案 3 :(得分:0)
这项任务值得怀疑,因为你很容易最终调用定义不明确的行为。
实际上,我们可以使用它,因为结构的类型是int
,与指针类型相同,并且严格别名规则中有一个例外。
但仍存在填充问题,因此我们必须确保整数之间不存在填充。
模糊的结果是这样的:
// BAD. Don't write code like this!
#include <stddef.h>
#include <stdio.h>
typedef struct
{
int width;
int height;
} rect;
int main (void)
{
rect my_rectangle;
my_rectangle.width = 4;
my_rectangle.height = 6;
int* ptr = (int*)&my_rectangle;
*ptr /= 2;
_Static_assert(offsetof(rect, height) == sizeof(int), "Padding detected.");
ptr++;
*ptr /= 2;
printf("%d %d", my_rectangle.width, my_rectangle.height);
return 0;
}
使用union
代替更好的做法。我们仍然会有相同的填充问题,但不必担心严格的别名。并且代码变得更容易阅读:
#include <stddef.h>
#include <stdio.h>
typedef union
{
struct
{
int width;
int height;
};
int array[2];
} rect;
int main (void)
{
rect my_rectangle;
my_rectangle.width = 4;
my_rectangle.height = 6;
_Static_assert(offsetof(rect, height) == sizeof(int), "Padding detected.");
my_rectangle.array[0] /= 2;
my_rectangle.array[1] /= 2;
printf("%d %d", my_rectangle.width, my_rectangle.height);
return 0;
}