我编写这段代码是为了遍历结构的成员。它工作正常。我可以对具有混合类型元素的结构使用类似的方法吗,即一些整数、一些 float 和...?
#include <stdio.h>
#include <stdlib.h>
struct newData
{
int x;
int y;
int z;
} ;
int main()
{
struct newData data1;
data1.x = 10;
data1.y = 20;
data1.z = 30;
struct newData *data2 = &data1;
long int *addr = data2;
for (int i=0; i<3; i++)
{
printf("%d \n", *(addr+i));
}
}
最佳答案
在 C 语言中,“工作正常”还不够好。因为你的编译器被允许这样做:
struct newData
{
int x;
char padding1[523];
int y;
char padding2[364];
int z;
char padding3[251];
};
当然,这是一个极端的例子。但是你明白了一般的想法;不能保证您的循环会工作,因为不能保证 struct newData
等同于 int[3]
。
所以不,在一般情况下这是不可能的,因为在特定情况下并不总是可能的!
现在,您可能会想:“这是什么白痴决定的?!”嗯,我不能告诉你,但我可以告诉你为什么。计算机彼此之间非常不同,如果您希望代码运行得更快,那么编译器必须能够选择如何编译代码。这是一个例子:
处理器 8 有一条指令获取单个字节,并将它们放入寄存器中:
GETBYTE addr, reg
这适用于这个结构:
struct some_bytes {
char age;
char data;
char stuff;
}
struct some_bytes
可以愉快的占用3个字节,代码速度很快。但是处理器 16 呢?它没有GETBYTE
,但有GETWORD
:
GETWORD even_addr, reghl
这只接受一个偶数地址,并读取两个字节;一个进入寄存器的“高”部分,一个进入寄存器的“低”部分。为了使代码更快,编译器必须这样做:
struct some_bytes {
char age;
char pad1;
char data;
char pad2;
char stuff;
char pad3;
}
这意味着代码可以运行得更快,但也意味着您的循环将无法运行。不过没关系,因为它是一种叫做“未定义行为”的东西;允许编译器假定它永远不会发生,如果它确实发生了,则行为是未定义的。
事实上,您已经遇到过这种行为!您的特定编译器正在执行此操作:
struct newData
{
int x;
int pad1;
int y;
int pad2;
int z;
int pad3;
};
因为您的特定编译器将 long int
定义为 int
长度的两倍,所以您可以这样做:
| x | pad | y | pad | z | pad |
| long no.1 | long no.2 | long no.3 |
| int | | int | | int |
正如您从我不稳定的图表中看出的那样,该代码是不稳定的。它可能不会在其他任何地方工作。更糟糕的是,如果您的编译器足够聪明的话,它能够做到这一点:
for (int i=0; i<3; i++) { printf("%d \n", *(addr+i)); }
Hmm...
addr
is fromdata2
which is fromdata1
which is a pointer to astruct newData
. The C specification says that only the pointer to the start of the struct will ever be dereferenced, so I can assume thati
is always0
in this loop!for (int i=0; i<3 && i == 0; i++) { printf("%d \n", *(addr+i)); }
That means it only runs once! Hooray!
printf("%d \n", *(addr + 0));
And all I need to compile is this:
int main() { printf("%d \n", 10); }
Wow, the programmer will be so pleased that I've managed to speed this code up so much!
你不会高兴的。事实上,您会遇到意想不到的行为,并且无法找出原因。但是,如果您编写的代码没有未定义行为,并且您的编译器做了类似的事情,您会感到高兴。所以它留下来。
关于c - 在 C 中使用指针循环遍历结构元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52859148/