下面是我创建的一些代码,旨在更好地理解C如何使用结构。
正如您可能猜到的那样,我没有得到我想要的结果。
我不明白的是如何访问结构中的结构而我不知道这段代码实际上在做什么。
更清楚的是,此代码无法正常运行。它不打印所需的值。它不是从Value或Suit打印3或4。
显然我使用的编辑器没有正确保存文件。当我手工编译时,我得到了我期望的结果。对困惑感到抱歉。
#include <stdio.h>
struct card
{
unsigned int value;
unsigned int suit;
};
struct board
{
struct card deck[52];
};
int main()
{
struct board b;
b.deck[0].value = 3;
b.deck[0].suit = 4;
printf("Card Value: %d Suit: %d \n", b.deck[0].value, b.deck[0].suit);
return 0;
}
答案 0 :(得分:2)
首先确定您的结构是真正的“C”结构还是“C ++结构”。虽然它们在键入时都相似(或相同),但如果使用C ++编译器,要获得真正的“C结构”,则需要在结构周围添加以下内容:
extern "C" {
... // true C structs go here
}
请注意,这只是编译器如何管理内存的一个示例,真正的编译器以优化底层硬件使用的方式管理内存。因此,编译器的实际数字,偏移量或操作顺序可能是错误的;但是,总的想法是一样的。
使用C结构,字段的符号(名称)将转换为偏移量。因此,当您使用C结构时,编译器会根据每个字段所需的空间(或该空间之后与内存子系统对齐的下一个地址)构建一个偏移表。稍后当您访问该字段时,正在运行的程序会将偏移量添加到结构开头的地址。
struct MyStruct {
int x;
int y;
int z;
};
struct MyStruct coordinates;
coordinates.x = 3;
coordinates.y = 5;
coordinates.z = 7;
// assuming an int takes 4 bytes, and addressing is one address per byte
// the running (conceputual) code might look like
I've labeled address 0x00002300 as "coordinate"
I've labeled ".x" as "+0";
I've labeled ".y" as "+4";
I've labeled ".z" as "+8";
这将使代码执行以下内存分配
set 0x00002300 + 0 (which is 0x00002300) to 0x00000003
set 0x00002300 + 4 (which is 0x00002304) to 0x00000005
set 0x00002300 + 8 (which is (0x0002308) to 0x00000007
请注意,在此理论示例中,编译器确保偏移量足以容纳值。真实编译器可能对int使用多于或少于+4的偏移量,因为它们的整数可能占用多于或少于4个字节,地址可能不是每个字节一个地址,或者内存子系统可能无法获取来自某些地址的int。 (许多内存子系统必须将数据“对齐”到数据总线的宽度。)
当您开始在数组中混合时,编译器会记录整个结构的大小,并将其用作基于数组索引的偏移量。所以
struct MyStruct coordinates[10];
coordinates[3].x = 3;
coordinates[3].y = 5;
coordinates[3].z = 7;
// assuming an int takes 4 bytes, addressing is one address per byte,
// and the entire "coordinates" struct takes up 12 bytes,
// the running (conceputual) code might look like
I've labeled address 0x00002300 as "coordinate"
I've labeled ".x" as "+0";
I've labeled ".y" as "+4";
I've labeled ".z" as "+8";
I've labeled the coordinate offset to be +12 which is "C" in Hex
这将使代码执行以下内存分配
set 0x00002300 + (3*c = 0x24) + 0 (which is 0x00002324) to 0x00000003
set 0x00002300 + (3*c = 0x24) + 4 (which is 0x00002328) to 0x00000005
set 0x00002300 + (3*c = 0x24) + 8 (which is (0x000232c) to 0x00000007
对于C ++结构,它们实际上是C ++类,其“默认”范围设置为“public”,所以
struct MyStruct {
int x;
int y;
int z;
};
由没有周围的“extern”C“{”指令的C ++编译器编译,将被视为
class MyStruct {
public:
int x;
int y;
int z;
};
并且将严重依赖于构造函数,copy-Constructor等的默认实现。
答案 1 :(得分:1)
你的程序没有问题..你想要的输出是什么?
$ gcc test.c
$ ./a.exe
Card Value: 3 Suit: 4
答案 2 :(得分:1)
通过下标访问struct
的成员:board.deck
访问由本地变量deck
保留的结构实例的board
成员。 board.deck
是card
的数组,因此进一步下标(通过数组括号表示法)用于访问单个card
实例。然后,点符号用于访问card
中此第一个board
结构的成员。
答案 3 :(得分:0)
您的程序正确且没有错误。