6.3 sizeof(4)
(10)计算结构变量的大小就必须讨论数据对齐问题。为了使CPU存取的速度最快(这同CPU取数操作有关,详细的介绍可以参考一些计算机原理方面的书),C++(www.cppentry.com)在处理数据时经常把结构变量中的成员的大小按照4或8的倍数计算,这就叫数据对齐(data alignment)。这样做可能会浪费一些内存,但在理论上CPU速度快了。当然,这样的设置会在读写一些别的应用程序生成的数据文件或交换数据时带来不便。MS VC++(www.cppentry.com)中的对齐设定,有时候sizeof得到的与实际不等。一般在VC++(www.cppentry.com)中加上#pragma pack(n)的设定即可。或者如果要按字节存储,而不进行数据对齐,可以在Options对话框中修改Advanced Compiler选项卡中的"Data Alignment"为按字节对齐。
(11)sizeof操作符不能用于函数类型、不完全类型或位字段。不完全类型指具有未知存储大小数据的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。
面试例题5:说明sizeof的使用场合。
答案:
(1)sizeof操作符的一个主要用途是与存储分配和I/O系统那样的例程进行通信。例如:
- void *malloc(size_t size),
- size_t fread(void * ptr, size_t size, size_t nmemb, FILE * stream)
(2)用它可以看看某种类型的对象在内存中所占的单元字节。例如:
- void * memset(void * s, int c, sizeof(s))
(3)在动态分配一对象时,可以让系统知道要分配多少内存。
(4)便于一些类型的扩充。在Windows中有很多结构类型就有一个专用的字段用来存放该类型的字节大小。
(5)由于操作数的字节数在实现时可能出现变化,建议在涉及操作数字节大小时用sizeof代替常量计算。
(6)如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小。
面试例题6:How many bytes will be occupied for the variable (definition: int **a[3][4])?(这个
数组占据多大空间?)[中国某著名计算机金融软件公司2005年面试题]
A.64 B.12 C.48 D.128
解析:sizeof问题,3×4×4=48。
答案:C
面试例题7:Find the defects in each of the following programs, and explain why it is incorrect.(找出下面程序的错误,并解释它为什么是错的。)[中国台湾某著名杀毒软件公司2005年、2007年面试题]
- #include <iostream>
- #include <string>
- using namespace std;
-
- int main(int argc, char* argv[]) {
- //To output "TrendMicroSoftUSCN"
-
- string strArr1[]=
- {"Trend","Micro","Soft"};
- string *pStrArr1=new string[2];
- pStrArr1[0]="US";
- pStrArr1[1]="CN";
-
- for(int i=0;i<sizeof(strArr1)
- /sizeof(string);i++)
- cout<<strArr1[i];
- for(int j=0;j<sizeof(pStrArr1)
- /sizeof(string);j++)
- cout<<pStrArr1[j];
-
- return 0;
- }
解析:sizeof问题。本题在2005、2007两年的面试题中都出现过。
程序运行后输出:TrendMicroSoftUS。这是因为sizeof(pStrArr1)运算得出的结果是指针pStrArr1的大小,即4。这样就不能正确地输出"USCN"。而字符串strArr1是由3段构成的,所以sizeof(strArr1)大小是12。
首先要明确sizeof不是函数,也不是一元运算符,它是个类似宏定义的特殊关键字,sizeof()。括号内的内容在编译过程中是不被编译的,而是被替代类型,如int a=8;sizeof(a)。在编译过程中,不管a的值是什么,只是被替换成类型sizeof(int),结果为4。如果sizeof(a=6)呢?也是一样地转换成a的类型。但是要注意,因为a=6是不被编译的,所以执行完sizeof(a=6)后,a的值还是8,是不变的。
请记住以下几个结论:
(1)unsigned影响的只是最高位bit的意义(正/负),数据长度是不会被改变的,所以:
- sizeof(unsigned int) == sizeof(int)
(2)自定义类型的sizeof取值等同于它的类型原形。如:
- typedef short WORD;sizeof(short) == sizeof(WORD)
(3)对函数使用sizeof,在编译阶段会被函数返回值的类型取代。如:int f1(){return 0;}。
- cout <<sizeof(f1()) <<endl; // f1()返回值为int,因此被认为是int
(4)只要是指针,大小就是4。如:
- cout <<sizeof(string*) <<endl; // 4
(5)数组的大小是各维数的乘积×数组元素的大小。如:
- char a[] ="abcdf ";
- int b[20] = {3, 4};
- char c[2][3] = { "aa ", "bb "};
- // 7,注意还有空格及'\0'
- cout <<sizeof(a) <<endl;
- cout <<sizeof(b) <<endl; // 20×4
- cout <<sizeof(c) <<endl; // 6
数组a的大小在定义时未指定,编译时给它分配的空间是按照初始化的值确定的,也就是7,包括'\0'。
所以上面的问题就解决得差不多了,sizeof(string)=4。
有的面试者说正确答案是将:
- for(i=0;i <sizeof(p)/sizeof(string);i++)
改为:
- for(i=0;i <sizeof(p)*2/sizeof(string);i++)
这样修改的结果能得到正确的输出结果,但却不是正确答案。sizeof(p)))只是指针大小为4,要想求出数组p指向数组的成员个数,应该为sizeof(*p)*2/sizeof(string)。这是因为指针p指向数组,则*p就是指向数组中的成员了,成员的类型是string型,那么sizeof(*p)为4,乘以2才是整个数组的大小。sizeof(p)的大小只是碰巧与sizeof(*p)大小一致罢了。