笔试遇到很多sizeof的小题,博主基础堪忧,怒总结如下,还是要巩固基础啊啊啊!

sizeof操作符 对象所占 栈内存空间的大小单位是字节

关键词:char  数组 指针 结构体 class

【注意】

① sizeof(NULL) 结果为1, "\n"转义字符算作1位

② 是栈内存的大小,不是堆,也不是静态全局区

class A1{
public:
int a;
static int b; //静态变量存放在全局数据区域
A1();
~A1();
}; void main(){
cout << sizeof(A1) <<endl; //输出结果 4
}

v

1.基本类型占内存大小

  32位机     64位机器
类型 字节数      
int 4      
char 1      
指针 4     8
bool 1      
float 4 浮点型    
short 2      
long 4      
double 8 双精度浮点型    

2.sizeof(指针)  任意类型指针,结果为4

3.sizeof(数组)    元素大小*n

注意:数组名作为参数传递时,退化为指针,不传值不退化

如 int data[30] = {1,2,3,4};

  sizeof(data); //30*4为120

  int getSize(int data[ ] ){

    return sizeof(data);} // 返回4

4.静态数组vs动态数组

静态数组见上文,动态数组是初始化一个指针

5 sizeof(class)

"类的大小就是类中成员变量(非静态,遵循内存对齐)加上指向虚函数表的指针 以及 指向虚基类表的指针加起来的和。"

一个空类所占空间为 1 ,单继承,多重继承的空类均为 1 ,虚继承的空类设计虚表,虚指针,所以是4

    cout<<"空类: " <<sizeof(A) <<endl;       //
cout<<"单继承空类: " <<sizeof(C) <<endl; //
cout<<"多继承空类: " <<sizeof(D) <<endl; //1
cout<<"虚单继承空类: " <<sizeof(E) <<endl;//
cout<<"虚多继承空类: " <<sizeof(F) <<endl;//

6.sizeof(函数),对函数的返回值类型,【注意】不能对void操作

7.sizeof( string )

本质上string是一个类,在同一库中相同一点是,无论你的string里放多长的字符串,它的sizeof()都是固定的,字符串所占的空间是从堆中动态分配的,与sizeof()无关。

32位机 vs2008测试 sizeof(string) 为32,  猜测是指针*  4*8=32,为什么??????????

    string str="he";
string str1[]={"hello", "program", "world"};
cout <<"string: "<<sizeof(str) <<"\n"<< //
"str1: " <<sizeof(str1) <<"\n"<<endl; //96

8.sizeof(struct)  结构体 字节对齐(以下为转载)

首先,可以用pack预处理指令来禁止字节对齐(很少用到)

#pragma pack(1)
struct a{
char cV;
int iV;
};
#pragma pack()

 

这是初学者问得最多的一个问题,所以这里有必要多费点笔墨。让我们先看一个结构体:

  1. struct S1
  2. {
  3. char c;
  4. int i;
  5. };

问sizeof(s1)等于多少聪明的你开始思考了,char占1个字节,int占4个字节,那么加起来就应该是5。是这样吗你在你机器上试过了吗也许你是对的,但很可能你是错的!VC6中按默认设置得到的结果为8。

扩展:

  1. struct bs
  2. {
  3. char c1;
  4. char c2;
  5. int a;
  6. };
  7. int main()
  8. {
  9. bs t;
  10. cout<<"sizeof(bs):"<<sizeof(bs)<<endl;//输出sizeof(bs): 8
  11. cout<<"sizeof(t):"<<sizeof(t)<<endl;//输出sizeof(t): 8
  12. }
  1. struct bs
  2. {
  3. char c1;
  4. int a;
  5. char c2;
  6. };
  7. int main()
  8. {
  9. bs t;
  10. cout<<"sizeof(bs):"<<sizeof(bs)<<endl;//输出sizeof(bs): 12
  11. cout<<"sizeof(t):"<<sizeof(t)<<endl;//输出sizeof(t): 12
  12. }

Why为什么受伤的总是我请不要沮丧,我们来好好琢磨一下sizeof的定义——sizeof的结果等于对象或者类型所占的内存字节数,好吧,那就让我们来看看S1的内存分配情况:
S1 s1 = { 'a', 0xFFFFFFFF };
定义上面的变量后,加上断点,运行程序,观察s1所在的内存,你发现了什么以我的VC6.0为例,s1的地址为0x0012FF78,其数据内容如下:
0012FF78: 61 CC CC CC FF FF FF FF
发现了什么怎么中间夹杂了3个字节的CC看看MSDN上的说明:
When applied to a structure type or variable, sizeof returns the actual size, which may include padding bytes inserted for alignment.
原来如此,这就是传说中的字节对齐啊!

一个重要的话题出现了。为什么需要字节对齐计算机组成原理教导我们这样有助于加快计算机的取数速度,否则就得多花指令周期了。为此,编译器默认会对结构体进行处理(实际上其它地方的数
据变量也是如此),让宽度为2的基本数据类型(short等)都位于能被2整除的地址上,让宽度为4的基本数据类型(int等)都位于能被4整除的地址上,以此类推。这样,两个数中间就可能需要加入填充字节,所以整个结构体的sizeof值就增长了。
让我们交换一下S1中char与int的位置:

  1. struct S2
  2. {
  3. int i;
  4. char c;
  5. };

看看sizeof(S2)的结果为多少,怎么还是8再看看内存,原来成员c后面仍然有3个填充字节,这又是为什么啊别着急,下面总结规律。

字节对齐的细节和编译器实现相关,但一般而言,满足三个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。

对于上面的准则,有几点需要说明:
1) 前面不是说结构体成员的地址是其大小的整数倍,怎么又说到偏移量了呢因为有了第1点存在,所以我们就可以只考虑成员的偏移量,这样思考起来简单。想想为什么。
结构体某个成员相对于结构体首地址的偏移量可以通过宏offsetof()来获得,这个宏也在stddef.h中定义,如下:
#define offsetof(s,m) (size_t)&(((s *)0)->m)
例如,想要获得S2中c的偏移量,方法为
size_t pos = offsetof(S2, c);// pos等于4

2) 基本类型是指前面提到的像char、short、int、float、double这样的内置数据类型,这里所说的“数据宽度”就是指其sizeof的大小。由于结构体的成员可以是复合类型,比如另外一个结构体,所以在寻找最宽基本类型成员时,应当包括复合类型成员的子成员,而不是把复合成员看成是一个整体。但在确定复合类型成员的偏移位置时则是将复合类型作为整体看待。
这里叙述起来有点拗口,思考起来也有点挠头,还是让我们看看例子吧(具体数值仍以VC6为例,以后不再说明):

  1. struct S3
  2. {
  3. char c1;
  4. S1 s;
  5. char c2
  6. };

S1的最宽简单成员的类型为int,S3在考虑最宽简单类型成员时是将S1“打散”看的,所以S3的最宽简单类型为int,这样,通过S3定义的变量,其存储空间首地址需要被4整除,整个sizeof(S3)的值也应该被4整除。c1的偏移量为0,s的偏移量呢这时s是一个整体,它作为结构体变量也满足前面三个准则,所以其大小为8,偏移量为4,c1与s之间便需要3个填充字节,而c2与s之间就不需要了,所以c2的偏移量为12,算上c2的大小为13,13是不能被4整除的,这样末尾还得补上3个填充字节。最后得到sizeof(S3)的值为16。

 

传送门:笔试题【C++基础】 sizeof题目

sizeof与strlen【C++基础】sizeof 与 strlen的区别

参考: C/C++ 笔试面试(1)—— sizeof

【C++基础】sizeof 数组 指针 空NULL的更多相关文章

  1. C语言基础 (9) 数组指针

    复习 只要把地址拿到就能这么操作.. (这里是合法的地址,不是野指针) 只有定义变量后,此变量的地址才是合法的地址 野指针就是保存没有意义地址的指针变量 操作野指针变量本身不会有任何问题 操作野指针所 ...

  2. go语言基础之数组指针做函数参数

    1.数组指针做函数参数 示例: package main //必须有个main包 import "fmt" //p指向实现数组a,它是指向数组,它是数组指针 //*p代表指针所指向 ...

  3. 嵌入式-C语言基础:数组指针

    定义一个数组指针,指向二维数组: int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}}; int (*p)[4];//定义二维指针数组 p=a;//指向二维数组 ...

  4. 数组类型与sizeof与指针的引用

    以char类型为例: char a[100];     //a类型为char[100]    &a类型为 char (*)[100]    *a类型为char char *p = a;     ...

  5. 释放内存触发断点及数组、指针的NULL初始化

    Visual Studio调试时,出现“触发一个断点”内存释放出现异常 数组和对应指针的NULL初始化 数组使用之前要先对其初始化 char Outi[4] = { NULL }; char Outj ...

  6. sizeof数组名和字符指针是有区别的

    sizeof数组名和字符指针是有区别的. #include <stdio.h> #include <stdlib.h> void change(char url[]); int ...

  7. PHP递归方式把一个数组里面的null转换为空字符串”的方法

    在一些接口的调用中,直接查询数据库出来的字段可能为null字段,但是为了简便前端的判断,需要把null转换成空字符串'',这个时候就需要递归的方式进行.直接上代码如下: //递归方式把数组或字符串 n ...

  8. [C++基础]那些容易被混淆的概念:函数/数组指针-指针函数/数组,类/函数模板-模板类/函数

    函数指针-指针函数 函数指针的重点是指针.表示的是一个指针,它指向的是一个函数.eg: int (*pf)(); 指针函数的重点是函数.表示的是一个函数,它的返回值是指针.eg: int* fun() ...

  9. C++基础 (8) 第八天 数组指针 模板指针 C语言中的多态 模板函数

    1昨日回顾 2 多态的练习-圆的图形 3多态的练习-程序员薪资 4员工管理案例-抽象类和技术员工的实现 employee.h: employee.cpp: technician.h: technici ...

随机推荐

  1. html 文件动态加载.PDI 流程图

    1 //javascript脚本 <script> window.onload = function () { var aid = document.getElementById(&quo ...

  2. 剑指offer_快速查找递增二维数组中是否存在目标

    [编程题]二维数组中的查找 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数     ...

  3. jquery获取文档高度和窗口高度的例子

    jquery获取文档高度和窗口高度,$(document).height().$(window).height() $(document).height():整个网页的文档高度 $(window).h ...

  4. 关于《Swift开发指南》背后的那些事

    时间轴(倒叙)2014年8月底在图灵出版社的大力支持下,全球第一本全面.系统.科学的,包含本人多年经验的呕心沥血之作<Swift开发指南>(配有同步视频课程和同步练习)全线重磅推出2014 ...

  5. 暑假集训(4)第六弹——— 组合(poj1067)

    题意概括:上一次,你成功甩掉了fff机械兵.不过,你们也浪费了相当多的时间.fff团已经将你们团团包围,并且逐步 逼近你们的所在地.面对如此危机,你不由得悲观地想:难道这acm之路就要从此中断?虽然走 ...

  6. root-systerm-bin是什么program

    root-systerm-bin是什么program http://packages.ubuntu.com/lucid/root-system-bin

  7. 《APUE》第6章笔记

    这一章主要介绍了口令文件和组文件的结构和一些围绕这些结构的函数. 口令文件即passwd就是在/etc/passwd中可以查阅.其结构是: 上图四个平台能支持的就用黑点表示. 因为加密口令这一项放在p ...

  8. 探索 Java 同步机制[Monitor Object 并发模式在 Java 同步机制中的实现]

    探索 Java 同步机制[Monitor Object 并发模式在 Java 同步机制中的实现] https://www.ibm.com/developerworks/cn/java/j-lo-syn ...

  9. input获取永久焦点

    $(function () { $('#test').blur(function () { var that = this; //或者用闭包 setTimeout(function () { $(th ...

  10. jQueryr .on方法解析

    .On() 其实.bind(), .live(), .delegate()都是通过.on()来实现的,.unbind(), .die(), .undelegate(),也是一样的都是通过.off()来 ...