|
|
|
|
移动端

1.11.1 数组求 sizeof

《程序员面试笔试真题与解析》本书针对当前各大 IT企业面试笔试中特性与侧重点,精心挑选了 3年以来近百家典型 IT企业的面试笔试真题,这些企业涉及业务包括系统软件、搜索引擎、电子商务、手机 APP、安全关键软件等,面试笔试真题非常具有代表性与参考性。本节为大家介绍数组求 sizeof。

作者:猿媛之家来源:机械工业出版社|2017-12-06 17:18


1.11.1 数组求 sizeof

【真题 157】在 32位计算环境下,定义有语句 int *p=new int[10],那么 sizeof(p)的值为()。

A.4 B.10 C.40 D.8 答案:A。 sizeof是 C/C++语言的关键字,它以字节的形式给出了其操作数的存储大小。对于本题而言, p是

一个指针,在 32位环境下,指针只占用 4个字节。所以,选项 A正确。

如果题目改成 int p[10],那么 sizeof(p)的值则是 40,因为此时 p是一个数组类型,数组中存放了 10个 int类型的元素,在 32位环境下,每个 int类型的变量占用 4个字节,因此,这个数组将会占用 40个字节。

所以,本题的答案为 A。

引申:在程序员笔试中经常会考察结构体变量的 sizeof的值,而这类题求职者经常容易做错。下面重点介绍 struct的 sizeof值的求解方法。

struct是一种复合数据类型,其构成元素既可以是基本数据类型,例如: int、double、float、short、 char等,也可以是复合数据类型,例如:数组、 struct、union等数据单元。

一般而言,struct(结构体)的 sizeof是所有成员对齐后长度相加,而 union(联合体)的 sizeof取昀大的成员变量长度。

在结构体中,编译器为结构体的每个成员按其自然边界( alignment)分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构体的地址相同。

字节对齐也称为字节填充,它是 C/C++编译器的一种技术手段,主要是为了在空间与复杂度上达到平衡。简单地讲,是为了在可接受的空间浪费的前提下,尽可能地提高对相同运算过程的昀少(快)处理。字节对齐的作用不仅便于 CPU的快速访问,使 CPU的性能达到昀佳,同时合理地利用字节对齐可以有效地节省存储空间。例如 32位计算机的数据传输值是 4 字节,64位计算机的数据传输值是 8字节,这样,在默认的情况下,编译器会对 struct进行( 32位机) 4的倍数或( 64位机)8的倍数的数据对齐。对于 32位机来说,4字节对齐能够使 CPU访问速度提高,例如一个 long类型的变量,如果跨越了 4字节边界存储,那么 CPU要读取两次,这样效率就低了,但需要注意的是,如果在 32位计算机中使用 1字节或者 2字节对齐,不仅不会提高效率,反而会使变量访问速度降低。

在默认情况下,编译器为每一个变量或数据单元按其自然边界条件分配空间。一般地,可以通过下面的方法来改变缺省的边界条件:

1)使用伪指令

#pragma pack (n),C语言编译器将按照 n个字节对齐。

2)使用伪指令

#pragma pack (),取消自定义字节对齐方式。

3)另外,还有如下的一种方式: _attribute((aligned (n))),让所作用的结构体成员对齐在 n字节自然边界上。如果结构体中有成员的长度大于 n,则按照昀大成员的长度来对齐。 _attribute_ ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。

例如以下数据结构:

  1. struct test  
  2. {  
  3. char x1;  
  4. short x2;  
  5. float x3;  
  6. char x4;  
  7. }; 

由于编译器默认情况下会对 struct作边界对齐,结构的第一个成员 x1,其偏移地址为 0,占据了第 1个字节,第二个成员 x2为 short类型,其起始地址必须 2字节对界,因此,编译器在 x2和 x1之间填充了一个空字节。结构的第三个成员 x3和第四个成员 x4恰好落在其自然边界地址上,在它们前面不需要额外的填充字节。在 test结构体中,成员 x3要求 4字节对界,是该结构所有成员中要求的昀大边界单元,因而 test结构的自然边界条件为 4字节,所以编译器在成员 x4后面填充了 3个空字节。整个结构所占据空间为 12字节。

再例如有以下数据结构:

  1. struct s1  
  2. {  
  3. short d;  
  4. int a;  
  5. short b;  
  6. }a1; 

在 32位机器下,short型占 2个字节,int型占 4个字节,所以,为了满足字节对齐的要求,变量 d除了自身所占用的 2个字节外,还需要再填充 2个字节,变量 a占用 4个字节,变量 b除了自身占用的 2个字节,还需要 2个填充字节,所以,昀终 s1的 sizeof值为 12。

字节对齐的细节和编译器实现相关,但一般而言,满足以下三个准则:

1)结构体变量的首地址能够被其昀宽基本类型成员的大小所整除。

2)结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节。

3)结构体的总大小为结构体昀宽基本类型成员大小的整数倍,如有需要编译器会在昀末一个成员之后加上填充字节。

需要注意的是,基本类型是指前面提到的像 char、short、int、float、double这样的内置数据类型,这里所说的“数据宽度”就是指其 sizeof的大小,在 32位机器上,这些基本数据类型的 sizeof大小分别为 1、2、4、4、8。由于结构体的成员可以是复合类型,所以,在寻找昀宽基本类型成员时,应当包括复合类型成员的子成员,而不是把复合成员看成是一个整体,例如一个结构体中包含另外一个结构体成员,那么此时昀宽基本类型成员不是该结构体成员,而是取基本类型的昀宽值。但在确定复合类型成员的偏移位置时,则是将复合类型作为整体看待,即复杂类型(如结构体)的默认对齐方式是它昀长的成员的对齐方式,这样在成员是复杂类型时,可以昀小化长度,达到程序优化的目的。

【真题 158】在 32位计算环境下,定义有语句 char str[] = "abcde";,那么 sizeof(str)的值为()。

A.1 B.4 C.5 D.6 答案:D。 sizeof是 C/C++语言中的关键字,它以字节的形式给出了其操作数的存储大小。本题中,语句 char str[] = "abcde";在内存中实际存储为一个字符数组: {‘a’,‘b’,‘c’,‘d’,‘e’,‘\0’},昀容

易忽视的就是字符串末尾的结束符 ‘\0’。同时,需要将 strlen与 sizeof进行区别,strlen执行的是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符 ‘\0’为止,然后返回计数器值,很显然,本题中,字符串 str的 strlen的值为 5,而字符串 str的 sizeof的值为 6,因为除了实际能看到的字符外,数组中还存储了字符串的结束符‘\0’,这个结束符也需要占用一个字节的存储空间。因此,选项 D正确。

【真题 159】在某 32位系统下, C++程序如下所示:

  1. char str[] = "http://www.tianya.com"(长度为21)  
  2. char *p = str;  
  3. sizeof (str) = ?(1)  
  4. sizeof (p) = ?(2)  
  5. void foo(char str[100])  
  6. {  
  7. sizeof(str) = ?(3)  
  8. }  
  9. void *p = malloc(100);  
  10. sizeof (p) = ?(4) 

(1)、(2)、( 3)和(4)处分别填写的值为()。

A.22, 22, 100, 100 B.4, 4, 4, 4 C.22, 4, 4, 4 D.22, 4, 100, 4答案:C。本题中, str是字符数组类型,数组的长度为 22(包括 21个字符和字符串结束符 ‘\0’),sizeof(str)表示

的是这个数组类型占用的空间,所以,值是 22。而 p是一个指向字符的指针,在 32位的系统下,指针变量占用的存储空间为 4个字节,因此, sizeof(p)的值为 4;在 C/C++语言中,当数组类型作为参数传递的时候,都会被转变为指针类型,因此, foo函数中的 str实际上是一个指向字符的指针(在参数传递的过程中数组会退化为指针),因此,第二个 str的 sizeof的值为 4。对于 void* p而言, p还是一个指针类型,在 32位的系统下,任何指针类型的数据都会占用 4个字节,因此, sizeof(p)=4。所以,选项 C正确。

【真题 160】在 C语言中,有数组定义如下: char array[]="China";,则数组 array所占用的空间为()。

A.4个字节 B.5个字节 C.6个字节 D.7个字节答案:C。在 C/C++语言中,字符串都是以字符 ‘\0’作为结束符。因此,字符串“ China”在内存中实际存储的

值为{‘C’,‘h’, ‘i’,‘n’,‘a’,‘\0’},一共占用 6个字节。所以,选项 C正确。

【真题 161】有以下程序:

  1. void main(void)  
  2. {  
  3. char a[7] = "a0\0a0\0";  
  4. int i, j;  
  5. i = sizeof(a);  
  6. j = strlen(a);  
  7. printf("%d, %d\n", i, j);  

程序运行后的输出结果是()。

A.2,2B.7,6 C.6,2D.7,2 答案:D。本题中,sizeof(a)的功能是求出字符串中的字符占用存储空间的大小,本题中,由于字符数组 a的

长度定义为 7,而每个 char类型的长度在 32位计算机下为 1个字节,i的值为 7。函数 strlen(a)的功能是求出字符串 a的长度,而每个字符串都以‘ \0’为字符串的结束标记,当遇到第一个‘ \0’字符时, strlen就认为字符串结束了, j的值为 2。所以,选项 D正确。

【真题 162】有如下代码:

  1. char *string_a = (char *)malloc(100*sizeof(char));  
  2. char string_b[100]; 

在 64位平台机器下, sizeof(string_a)与 A.8,100 答案:A。 sizeB.100,8  of(string_b)的值分别是(C.100,100    )、(D.8,8  )。

本题中,string_a是一个字符指针,不管它指向的空间有多大,它本身的空间是固定的。在 64位机器下,一个指针的大小是 8,单位是字节。而 string_b是一个字符数组,长度为 100,在 64位机器下,每个 char占用 1个字节, string_b的 sizeof为 100。所以,选项 A正确。

【真题 163】有如下代码:

  1. int b[][3] = {{1},{3,2},{4,5,6},{0}}; 

在 32位机器下, sizeof(b)的值为()。

A.4 B.12 C.28 D.48答案:D。本题中,变量 b为一个二维整型数组,该二维数组规定了列的数量为 3,而行的数量却没有显式写

明,根据数组中内容可知,该数组一共有 4行,每行又有 3列。根据约定,当初始化数据的语句中没有写明元素的值时,该值默认为 0。所以,语句 int b[][3] = {{1},{3,2},{4,5,6},{0}}等价于语句 int b[ ][3] = {{1, 0, 0},{3,2, 0},{4,5,6},{0, 0, 0}}。

在 32位机器下,每个 int型变量占 4个字节,二维数组 b的 sizeof值 sizeof(b)=4*3*4=48。所以,选项 D正确。

喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书频道活动讨论群:365934973

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

嬴在用户:Web人物角色创建和应用实践指南

您如何保证您的网站确实给予用户他们所需要的,并对您产生商业成果?您需要了解谁是您的用户,您的用户的目标、行为和观点是什么,还要把他...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊