sizeof-面试题

下面是一道笔试题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct {
short a1;
short a2;
short a3;
}A;
struct {
long a1;
short a2;
}B;
int main()
{
char *ss1 = "0123456789";
char ss2[] = "0123456789";
char ss3[100] = "0123456789";
int ss4[100];
char q1[] = "abc";
char q2[] = "a\n";
char *q3 = "a\n";
char *str1 = (char *)malloc(100);
void *str2 = (void *)malloc(100);
printf("%d ", sizeof(ss1)); //ss1是指针
printf("%d ", sizeof(ss2)); //ss2是数组,计算到"\0"的位置,因此是(10+1)
printf("%d ", sizeof(ss3)); //在内存中预分配的空间大小,100*1
printf("%d ", sizeof(ss4));
printf("%d ", sizeof(q1));
printf("%d ", sizeof(q2));
printf("%d ", sizeof(q3));
printf("%d ", sizeof(A));
printf("%d ", sizeof(B));
printf("%d ", sizeof(str1));
printf("%d ", sizeof(str2));
return 0;
}

在64位linux系统上此程序的输出为:

8 11 100 400 4 3 8 6 16 8 8

在32位机上的输出为:

4 11 100 400 4 3 4 6 8 4 4 

解释:32位机器上long和int都是4字节,64位机器上,long是8字节,int是4字节

sizeof和strlen之间的区别

接上面的例子分析:

1
2
3
4
strlen(ss3)
//结果为10,strlen内部实现是用一个循环计算字符串的长度,直到"\0"为止
strlen(ss4)
//错误,strlen的参数只能是char *,且必须是以"\0"结尾的

总结

  • sizeof操作符的结果类型时size_t,它在头文件中的typedef为unsigned int类型。该类型保证能容纳实现所建立的最大对象的字节大小

再来一题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int GetSize(int data[])
{
return sizeof(data);
}
int _tmain(int argc, _TCHAR* argv[])
{
int data1[] = {1, 2, 3, 4, 5};
int size1 = sizeof(data1);
int* data2 = data1;
int size2 = sizeof(data2);
int size3 = GetSize(data1);
printf("%d, %d, %d", size1, size2, size3);
}

输出:“20, 4, 4”。data1是一个数组,sizeof(data1)是求数组的大小。这个数组包含5个整数,每个整数占4字节,因此总共是20字节。data2声明为指针,尽管它指向了数组data1的第一个数字,但它的本质仍然是一个指针。在32位系统上,对任意指针求sizeof,得到的结果都是4。在C/C++中,当数组作为函数的参数进行传递时,数组就自动退化为同类型的指针。因此尽管函数GetSize的参数data被声明为数组,但它会退化为指针,size3的结果仍然是4。—《剑指offer》P37