sizeof规则

本文探讨了C语言中sizeof操作符的工作原理,重点在于栈的大小计算和静态变量的排除。在16位系统中,通过一个具体的例子解释了结构体的字节对齐规则:数据成员自对齐和结构体总长度对齐。通过这两个规则,可以推断出结构体在内存中的布局,并揭示了可能存在的字节浪费现象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

明确本质:sizeof是计算栈的大小,故静态变量不算在内
以下题来自牛客网,解析来自牛友,侵删

在一个16位的机器,以下结构由于边界对齐浪费了多少空间()
struct{
     char a;
     int b;
     char c;
}
正确答案: D   你的答案: C (错误)

8
4
6
2

(注意!!是结构体)
结构体中字节对齐有两条规则:
数据成员自对齐,即数据成员起始地址为数据类型长度的整数倍,如该题int型b只能从024...等地址处开始放;
结构体总长度是结构体中有效对齐值的整数倍,有效对齐值,如该题没明确指出,则为最长数据成员(int b)长度的整数倍;
其内存示意图如下:

这里写图片描述

本题是16位机器,char型占1个字节,int型占2个字节。
结构体中字节对齐有两条规则:
数据成员自对齐,即数据成员起始地址为数据类型长度的整数倍,如该题int型b只能从0,2,4…等地址处开始放;
结构体总长度是结构体中有效对齐值的整数倍,有效对齐值,如该题没明确指出,则为最长数据成员(int b)长度的整数倍;
根据上面两条规则,画出内存示意图。根据规则1,int b从2处开始放,此时结构体总长度为(1 + 1 + 2 + 1 = 5);再根据规则2,结构体总长度应为2的整数倍,故应为6.描红的两个字节表示被浪费的。

32位操作系统gcc编译器环境下,下面程序的运行结果为()
#include <iostream>
using namespace std;
class A {
public:
    int b;
    char c;
    virtual void print() {
        cout << "this is father’s fuction! " << endl;
    }
};
class B: A {
public:
    virtual void print() {
        cout << "this is children’s fuction! " << endl;
    }
};
int main(int argc, char * argv[]) {
    cout << sizeof(A) << "" << sizeof(B) << endl;
    return 0;
}

正确答案: A   你的答案: C

12 12
8 8
9 9
12 16
添加笔记
已收藏
纠错
本题知识点

C/C++  搜狐
参考解析 添加解析
18

推荐
Aesthetic92头像Aesthetic92
答案:选A
答案解析:类的大小只与成员变量(非static数据成员变量)和虚函数指针有关,还要考虑到对齐.
那么类A的大小等于4个字节 + 4个字节(考虑对齐) + 4个字节(指向虚函数的指针)=12字节;
类B的大小就是等于类A的大小12个字节.
因为在基类中存在虚函数时,派生类会继承基类的虚函数,因此派生类中不再增加虚函数的存储空间(因为所有的虚函数共享一块内存区域),而仅仅需要考虑派生类中添加进来的非static数据成员的内存空间大小。所以类B大小为12B
下面哪些调用转换支持可变长度参数
正确答案: A   你的答案: 空 (错误)

cdecl
stdcall
pascal
fastcal
添加笔记
收藏
纠错
本题知识点

C/C++  微软
参考解析 添加解析
4

推荐
star_liux头像star_liux
_cdecl允许调用者传递不确定数量的参数,pascal, fastcal 返回方式和 stdcall相同
编辑于 2015-02-09 16:26:57 回复(1)
更多回答(2条)
40

心中的日月头像心中的日月
__cdecl __fastcall与__stdcall,三者都是调用约定(Calling convention),它决定以下内容:1)函数参数的压栈顺序,2)由调用者还是被调用者把参数弹出栈,3)以及产生函数修饰名的方法。
1、__stdcall调用约定:函数的参数自右向左通过栈传递,被调用的函数在返回前清理传送参数的内存栈。
2、_cdecl是CC++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。注意:对于可变参数的成员函数,始终使用__cdecl的转换方式。
3、__fastcall调用约定:它是通过寄存器来传送参数的(实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈)。
4、thiscall仅仅应用于"C++"成员函数。this指针存放于CX寄存器,参数从右到左压。thiscall不是关键词,因此不能被程序员指定。
5、nakedcall采用1-4的调用约定时,如果必要的话,进入函数时编译器会产生代码来保存ESI,EDI,EBX,EBP寄存器,退出函数时则产生代码恢复这些寄存器的内容。naked call不产生这样的代码。naked call不是类型修饰符,故必须和_declspec共同使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值