1.sizeof的用法: 计算的是分配的内存空间的大小,不受存储内容大小的影响。 #include<stdio.h>
int main()
{
int a=0,b=0,c=0,d=0;
char *str1="absde";
char str2[]="absde";
char str3[8]={'a'};
char ss[]="0123456789";
a=sizeof(str1); //8 指针分配的是8个字节
b=sizeof(str2); //6 5+反斜杠0
c=sizeof(str3); //8 返回的分配的内存大小,数组的大小是8
d=sizeof(ss); //11 如果数组没有指定,则返回的字字符串长度+反斜杠0
printf("%d,%d,%d,%d\n",a,b,c,d);
return 0;
}
liuzj@ET302Buildver:~/zhanghong/make$ ./a.out
8,6,8,11
数组——编译时分配的数组空间大小;
指针——存储该指针所用的空间大小(存储该指针的地址的长度,是长整型,应该为4);
类型——该类型所占的空间大小;
对象——对象的实际占用空间大小;
函数——函数的返回类型所占的空间大小。函数的返回类型不能是void。
2.strlen
计算字符串的长度,以\0'为字符串结束标记。不算反斜杠0. strlen(...)是函数,要在运行时才能计算。参数必须是字符型指针(char*)。当数组名作为参数传入时,实际上数组就退化成指针。
#include<stdio.h>
#include<string.h>
int main()
{
int A=0,B=0,C=0,D=0,E=0;
char *str1="absde";
char str2[]="absde";
char str3[8]={'a'};
char ss[]="0123456789";
A=strlen(str1); //数大小5
B=strlen(str2); //数大小5
C=strlen(str3); //数大小1
D=strlen(ss); //数大小10
printf("%d,%d,%d,%d\n",A,B,C,D);
return 0;
}
liuzj@ET302Buildver:~/zhanghong/make$ ./a.out
5,5,1,10
liuzj@ET302Buildver:~/zhanghong/make$
3.二者区别:
(1).计算结构体的时候, 计算结构体的问题要考虑对齐 的问题。
(2).联合体的大小是联合体中的最长的。
(3).枚举的大小是根据枚举的类型。
struct stu1 { int i; char c; int j; };
用sizeof求该结构体的大小,发现值为12。int占4个字节,char占1个字节,结果应该是9个字节才对啊,为什么呢?
先介绍一个相关的概念——偏移量。偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。显然,结构体变量中第一个成员的地址就是结构体变量的首地址。因此,第一个成员i的偏移量为0。第二个成员c的偏移量是第一个成员的偏移量加上第一个成员的大小(0+4),其值为4;第三个成员j的偏移量是第二个成员的偏移量加上第二个成员的大小(4+1),其值为5。
然而,在实际中,存储变量时地址要求对齐,编译器在编译程序时会遵循两条原则:
(1)结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
(2)结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数。
上面的例子中前两个成员的偏移量都满足要求,但第三个成员的偏移量为5,并不是自身(int)大小的整数倍。编译器在处理时会在第二个成员后面补上3个空字节,使得第三个成员的偏移量变成8。结构体大小等于最后一个成员的偏移量加上其大小,上面的例子中计算出来的大小为12,满足要求。
再来看另外一个例子:
struct stu2 { int k; short t; };
成员k的偏移量为0;成员t的偏移量为4,都不需要调整。但计算出来的大小为6,显然不是成员k大小的整数倍。因此,编译器会在成员t后面补上2个字节,使得结构体的大小变成8从而满足第二个要求。
由此可见,结构体类型需要考虑到字节对齐的情况,不同的顺序会影响结构体的大小。
对比下面两种定义顺序:
struct stu3 { char c1; int i; char c2; } struct stu4 { char c1; char c2; int i; }
虽然结构体stu3和stu4中成员都一样,但sizeof(struct stu3)的值为12而sizeof(struct stu4)的值为8。
sizeof计算嵌套的结构体大小
对于嵌套的结构体,需要将其展开。对结构体求sizeof时,上述两种原则变为:
(1)展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。
(2)结构体大小必须是所有成员大小的整数倍,这里所有成员计算的是展开后的成员,而不是将嵌套的结构体当做一个整体。
看下面的例子:
struct stu5 { short i; struct { char c; int j; } ss; int k; }
结构体stu5的成员ss.c的偏移量应该是4,而不是2。整个结构体大小应该是16。
下述代码测试原则2:
struct stu5 { char i; struct { char c; int j; } ss; char a; char b; char d; char e; char f; }
结构体ss单独计算占用空间为8,而stu5的sizeof则是20,不是8的整数倍,这说明在计算sizeof(stu5)时,将嵌套的结构体ss展开了,这样stu5中最大的成员为ss.j,占用4个字节,20为4的整数倍。如果将ss当做一个整体,结果应该是24了。
另一个特殊的例子是结构体中包含数组,其sizeof应当和处理嵌套结构体一样,将其展开,如下例子:
struct ss { float f; char p; int adf[3]; };
其值为20。float占4个字节,到char p时偏移量为4,p占一个字节,到int adf[3]时偏移量为5,扩展为int的整数倍,而非int adf[3]的整数倍,这样偏移量变为8,而不是12。结果是8+12=20,是最大成员float或int的大小的整数倍。

1812

被折叠的 条评论
为什么被折叠?



