可能重复:
Why isn’t sizeof for a struct equal to the sum of sizeof of each member?
在C中创建结构时,例如:
typedef struct student
{
int roll_no;
char* name;
int* pointer;
}student;
我注意到roll_no和name没有连续存储在内存中。这是如何运作的?如果目的是封装这些数据,那么它们是否连续存储会更好吗?编译器如何知道这些数据属于一起?
答案 0 :(得分:1)
编译器对齐结构的每个元素的开头以匹配体系结构的要求。 这通常意味着对齐位于单词边界上,但没有严格的规则。
typedef对齐无效 - 它只是创建一个对象的“速记引用”,可能就像一个结构。您可以将typedef视为同义词。
答案 1 :(得分:1)
name
确实没有与struct
一起存储:只存储指针。数据通常在struct
本身以外的区域动态分配。
要将名称与struct
一起存储,您需要将其作为数组。这种方法的缺点是字符串必须是固定长度的(即所有struct
s将分配足够的name
最大长度的内存量,或者您需要使用灵活的数组元素通过在name[]
的末尾声明struct
数组。最后一种方法的缺点是(1)分配变得更加复杂,(2)你不能创建这样的数组{ {1}} s,以及(3)结构中只能有一个灵活的数组。
答案 2 :(得分:0)
它们是连续存储的。只是char *名称中包含的地址在其他地方。要在内存中连续存储,请使用数组而不是指针。
这是它存储在内存中的方式,例如,struct的地址从1000(十进制)开始。
1000 roll_no
1004 name
1008 pointer
name和pointer是指针,因此它们将保存malloc分配的值(地址)。
s->name = malloc(100);
s->pointer = malloc(4);
在这种情况下,没有结构填充,因为所有都是整数(甚至是指针),这意味着它们是体系结构寄存器大小的大小(通常为32或64位)。
答案 3 :(得分:0)
数据是连续存储的,但由于优化和对齐字边界,可能会出现整体数据。对齐取决于您运行的处理器和选择的编译器选项。 (包装)
编译器将计算结构的偏移量,因此它可以在内存中进行查找以获取结构的元素。
答案 4 :(得分:0)
实际上在 struct
中struct student
{
int roll_no;
char* name;
int* pointer;
}
C完全符合您的要求(除了“结构填充”,但这是另一个故事)。假设英特尔处理器上有gcc
,结构由
int
的4个字节,后跟char *
指针的4个字节,后跟int *
指针指向指针 name 成员是一个指向char(s)的指针,通常是指向内存中某个字符串的指针。例如
char *string = "John Doe";
int value = 255;
struct student me;
me.roll_no = 15;
me.name = string;
me.pointer = &value;
这里 string 在内存中的某个位置 - 正如您所注意到的那样,它在结构之前已经被声明了。假设其内存位置为0x12345678
,值位于0x20000000
,结构位于0x22222222,因此我们有
0x12345678 : John Doe\0
...
0x20000000 : FF000000 // 255
...
0x22222222 : 0F0000001234567820000000
您看到0F000000
的结构为15
,字符串地址为12345678
,值为 20000000
地址。