Ima*_*n H 4 c pointers structure
我编写了这段代码来迭代结构的成员.它工作正常.我可以对具有混合类型元素的结构使用类似的方法,即一些整数,一些浮点数和......?
#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));
}
}
Run Code Online (Sandbox Code Playgroud)
在C中,"它工作正常"还不够好.因为允许您的编译器执行此操作:
struct newData
{
int x;
char padding1[523];
int y;
char padding2[364];
int z;
char padding3[251];
};
Run Code Online (Sandbox Code Playgroud)
当然,这是一个极端的例子.但是你得到了一般的想法; 它不能保证你的循环可以工作,因为它不能保证struct newData相当于int[3].
所以不,在一般情况下这是不可能的,因为在特定情况下并不总是可能!
现在,你可能会想:"白痴决定了什么?!" 好吧,我不能告诉你,但我可以告诉你为什么.计算机彼此非常不同,如果您希望代码快速运行,那么编译器必须能够选择如何编译代码.这是一个例子:
处理器8具有获取单个字节的指令,并将它们放入寄存器:
GETBYTE addr, reg
Run Code Online (Sandbox Code Playgroud)
这适用于这个结构:
struct some_bytes {
char age;
char data;
char stuff;
}
Run Code Online (Sandbox Code Playgroud)
struct some_bytes可以愉快地占用3个字节,代码很快.但是处理器16呢?它没有GETBYTE,但确实有GETWORD:
GETWORD even_addr, reghl
Run Code Online (Sandbox Code Playgroud)
这只接受偶数地址,并读取两个字节; 一个进入寄存器的"高"部分,一个进入寄存器的"低"部分.为了使代码快速,编译器必须这样做:
struct some_bytes {
char age;
char pad1;
char data;
char pad2;
char stuff;
char pad3;
}
Run Code Online (Sandbox Code Playgroud)
这意味着代码可以更快地运行,但这也意味着你的循环不起作用.那没关系,因为它叫做"未定义的行为"; 允许编译器假设它永远不会发生,如果它确实发生,则行为是未定义的.
事实上,你已经遇到过这种行为!你的特定编译器是这样做的:
struct newData
{
int x;
int pad1;
int y;
int pad2;
int z;
int pad3;
};
Run Code Online (Sandbox Code Playgroud)
因为您的特定编译器定义long int为长度的两倍int,所以您可以这样做:
| x | pad | y | pad | z | pad |
| long no.1 | long no.2 | long no.3 |
| int | | int | | int |
Run Code Online (Sandbox Code Playgroud)
正如你可以从我不稳定的图表中看到的那样,这段代码是不稳定的.它可能无法在其他任何地方工作.更糟糕的是,你的编译器,如果它很聪明,就能做到这一点:
Run Code Online (Sandbox Code Playgroud)for (int i=0; i<3; i++) { printf("%d \n", *(addr+i)); }嗯...
addr是data2这是data1这是一个指针struct newData.C规范说只有指向结构开头的指针才会被取消引用,所以我可以假设它i总是0在这个循环中!Run Code Online (Sandbox Code Playgroud)for (int i=0; i<3 && i == 0; i++) { printf("%d \n", *(addr+i)); }这意味着它只运行一次!万岁!
Run Code Online (Sandbox Code Playgroud)printf("%d \n", *(addr + 0));我需要编译的是:
Run Code Online (Sandbox Code Playgroud)int main() { printf("%d \n", 10); }哇,程序员会非常高兴我已经设法加快了这个代码的速度!
你不会高兴的.事实上,你会得到意想不到的行为,并且无法解决原因.但是如果您编写的代码没有未定义的行为,并且您的编译器已经做了类似的事情,那么您会很高兴.所以它保持不变.
| 归档时间: |
|
| 查看次数: |
376 次 |
| 最近记录: |