某童靴前天去理想国际某公司面试,回来在宿舍讨论了这样一道题:
VC++里,有一个空类,没有声明任何成员变量或函数,请问此空类占多大字节空间?
A、 0 B、 1 C、 4 D、8
当时考虑了32bit和64bit机器,并且指针地址是int型,32bit占4个字节或64bit占8个字节,因此选了C和D
后又想想,这没有操作指针,也就不需内存对齐(视VC++编译器会自动进行对齐优化),排除了C和D,选择了A
当时也考虑过侯捷老师译著的那本《深度探索C++对象模型》,C++中继承与多态在编译器中是如何区分的,所以0字节也不靠谱
但至少也不会仅占一个字节吧,因此当时首先就把B彻底killed
面试回来,在VC6.0、 VS2010、 g++(Linux 2.6.31-14)上编译,发现结果居然是:1
首先,我贴出测试代码:
然后,在各编译器上编译
其结果分别如下:
VC6.0 (XP Professional SP2 - 32bit)

VS2010 (Win7 Ultimate SP1 - 64bit)

g++(Ubuntu linux 2.6.31-14 - 64bit)

最后,分析为何结果会是:1
这里,先看看C++多态的内部实现
例如,有三个重载函数:
int add(int a, int b);
int add(int a, int b, int c);
float add(float a, float b);
C++编译器是如何上面三个函数呢?
_add_int_int
_add_int_int_int
_add_float_float
编译器压栈记录的是:函数名+参数类型+参数个数(注:返回值类型不足以区分多态)
知道了C++编译器如何处理和区分多态(重载类似)后,现在我们回到正题——sizeof(空类或空结构体)= 1
空类,没有任何成员变量或函数,即没有存储任何内容;
但是由于空类仍然可以实例化,即 ClassA A; cout<<"sizeof(A): "<<sizeof(A)<<endl;
一个类能够实例化,编译器就需给它分配内存空间,来指示类实例的地址
这里编译器默认分配了一个字节(如:char),以便标记可能初始化的类实例,同时使空类占用的空间也最少(即1字节)
分享到:
相关推荐
通过深入理解`sizeof`和`struct`结构体的内存对齐,开发者可以更好地控制内存使用,避免潜在的性能瓶颈,并优化代码的移植性。在实际编程中,尤其是涉及网络通信、数据序列化或硬件交互时,结构体的内存布局就显得尤...
sizeof(结构体)和内存对齐 sizeof(结构体)和内存对齐是C语言中一个重要的概念,它们之间存在着紧密的联系。sizeof(结构体)是指结构体在内存中的大小,而内存对齐是指编译器为了提高程序的效率和可移植性,对内存...
sizeof进行结构体大小的判断.sizeof进行结构体大小的判断.sizeof进行结构体大小的判断.
sizeof与结构体和共同体.PDF 特别特别难找的一本书,不下会后悔的
在本项目中,"socket传送结构体或类"是一个关键主题,这意味着我们需要通过Socket接口来传输自定义的结构体或类对象。下面将详细讨论这个主题。 首先,结构体(Struct)和类(Class)在C++中都是用于组织数据的工具...
当我们需要复制一个结构体或类实例时,通常有两种方式:浅拷贝和深拷贝。在本例中,我们关注的是浅拷贝,也就是内存拷贝。浅拷贝会直接复制对象在内存中的字节序列,而不考虑其内部可能存在的指针或其他复杂结构。这...
最后,如果结构体或类中包含虚函数,则需要额外加上虚函数表指针的空间(通常为4或8字节,取决于平台)。基类继承而来的子类在考虑虚函数时也会有所不同。 在实际编程中,合理利用数据对齐规则可以帮助开发者编写更...
如果结构体中包含C++特有的类型(如指针或动态分配的数组),那么直接读写可能会出现问题,因为它们在内存中可能不是连续的。此时,需要自定义序列化和反序列化逻辑。 在实际开发中,除了基本的结构体,我们还可能...
// 将结构体的起始地址进行强制转型,传入起始地址,用sizeof函数求出结构体的大小。} 这个算法比较简单,也没什么含量。但是希望大家有什么好的算法,也分享出来给大家,大家一起学习进步。
这可能会影响到结构体的实际大小,可以通过 sizeof 操作符来获取结构体所占的字节数。 例如,我们可以这样显示 `Student` 结构体的大小: ```c #include int main() { printf("Size of struct Student: %ld ...
与类不同,结构体不会自动进行垃圾回收,因此对于大量数据的操作效率较高。在某些情况下,我们可能需要操作非托管代码或直接访问内存地址,这时候就需要用到结构体指针。 #### C#结构体的定义 C#结构体可以通过...
`sizeof`运算符用于获取结构体或变量在内存中占用的字节数,这对于内存管理、计算数组大小等操作非常有用。例如`sizeof(struct cat)`会返回`cat`结构体的总大小。 7. **结构体变量赋值**: 同类型的结构体变量...
void* p2 = malloc(sizeof(struct GPIO_TypeDef)); struct GPIO_TypeDef *p1 = (struct GPIO_TypeDef *)p2; ``` 2. **在STM32中的应用**:在STM32的开发中,可能会遇到需要从一个地址读取GPIO外设信息的情况。...
在实际编程中,我们可以通过预处理器宏来获取结构体的大小,例如在C/C++中使用`sizeof`运算符: ```c printf("Size of MyStruct: %zu\n", sizeof(struct MyStruct)); ``` 这将输出结构体`MyStruct`的实际大小,包括...
i < sizeof(stus) / sizeof(struct stu); i++) { printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", ps[i].name, ps[i].num, ps[i].age, ps[i].group, ps[i].score); } ``` 以上就是C语言中关于...
C# 提供了多种方法来实现序列化,其中最简单的是使用`BinaryFormatter`类,但这种方法不适用于含有数组的结构体,因为它会产生额外的元数据信息。对于简单的结构体,我们可以手动实现序列化,如下: ```csharp ...
如果结构体包含复杂类型(如其他结构体或对象),则需要考虑递归转换或使用其他序列化库。此外,对于跨平台或多线程环境,还需要额外考虑内存管理和线程安全问题。 总结起来,这个"C#byte数组结构体互相转换示例...
对于空结构体,即使没有数据成员,编译器也会为其分配至少1字节的空间,以便于变量的识别和地址分配。 理解字节对齐对于优化代码性能和编写跨平台的代码至关重要。不同的编译器和硬件平台可能有不同的对齐策略,...
在C语言中,结构体(Struct)是一种复合数据类型,它允许我们将多个不同类型的变量组合成一个单一的实体。...结构体是C语言中不可或缺的一部分,尤其在构建高级数据结构(如链表、树、图等)时显得尤为重要。