一:是什么是size of
1:size of 是计算对象所占用的字节个数,通常是用来查看变量或结构体等所占用的字节个数。
eg:int a; sizeof(a); //计算a所占用的字节数
struct{int num; char b[]; int age;}person; sizeof(person); //计算整个结构person所占用的字节总数
2:size of 是c/c++中的一个操作符,其作用是返回一个对象类型所占用内存的字节数。
3:基本类型数据(short , int , double , float , long等)是和系统相关的,所以在不同系统下,用sizeof取的返回值可能不同。 一般的,在32位编译环境中,sizeof(int )的取值为4.
4:指针变量的sizeof
指针是用来记录一个对象的地址。既然是用来存放地址的,那么他当然等于计算机内部地址总线的宽度。所以在32位计算机中,一个指针变量的返回值必定是4(以字节为单位)。
eg: int *pi; char * pc="abcdefg";
int a=sizeof(pi) ; int b=sizeof(pc); //a和b的取值都等于4
指针变量的sizeof值与指针所指的对象没有任何关系,所有的指针变量所占内存大小都相等。
5:数组的sizeof
数组的sizeof值等于数组所占用的内存字节总数。
eg:char a1[]="abc"; int a2[3];
sizeof(a1); // 结果为四,字符串末尾还存在一个Null终止符
sizeof(a2); //结果为3*4=12,(依赖于int)
记住:sizeof是求对象占内存的字节数,而非求数组元素的个数。
如果要用来求数组的个数,则: int c1=sizeof(a1)/sizeof(char);
int c2=sizeof(a2)/sizeof(a2[0]);
6:结构体的sizeof (此类问题最为复杂,涉及到字节对齐的问题)
(1):什么是字节对齐:
现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。(1个字节等于8位二进制数)
(2):字节对齐的作用和原因:
1: 各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。
2:比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据 (即字节对齐的存在提高了存取数据的速度)
(3):字节对齐的本质:
在字节对齐的过程中,总有一些字节是浪费掉的,这样做的目的很简单,就是因为在大多数计算机体系结构中,对内存操作时按整字存取才能达到最高效率,相当于是以空间换取时间。
(4):关于结构体字节对齐(在没有#pragma pack宏的情况下) :
•原则1
数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。
•原则2
结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储。)
•原则3
收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。
二:什么是strlen函数
1:strlen函数所作的仅仅只是一个计数器的工作,它从内存中的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的区域)开始扫描,直到碰到第一个字符串结束符 '\0' 为止,然后返回计数器值(长度不包含 '\0')。
2:函数原型 : extern unsigned int strlen(char *) ;
头文件: string.h
格式:strlen(字符数组名) //参数必须是 char *;
功能:计算给定字符串的长度(unsigned int 型),不包括 '\0' ;
说明:返回字符串s的长度,不包括终止符Null 。
3:案列说明:
C语言中的strlen函数可以测量字符串的长度,比如测 char a[]="china"; char b[]={"china"}; 那么它可以测 char c[]={'c','h','i','n','a'};的长度吗?char d[]={'c','h','i','n','a','\0'};呢?
#include<stdio.h>
void main()
{
char a[]="china";
char b[]={"china"};
char c[]={'c','h','i','n','a'};
char d[]={'c','h','i','n','a','\0'};
printf("a=%d\nb=%d\nc=%d\nd=%d\n",strlen(a),strlen(b),strlen(c),strlen(d));
getch();
}
这个程序的结果是:
a=5
b=5
c=11 //这是因为c[]的长度是未知的,因此出来的结果也是未知的,可能是11,也可能是其他的数值,若为c[10],则其结果为5,以为c[]会在最后自动帮你补齐一个'\0',这样的结果就是5.
d=5
char str[6] = "abcxyz";
strlen(str)的返回值将是不确定的。因为str的结尾不是0,strlen()会继续向后检索,直到遇到'\0',而这些区域的内容是不确定的
三:strlen 和sizeof 的区别:
1:sizeof()返回的是变量或结构体所占用的字节数,不是实际长度,strlen()返回的是字符串的实际长度(不包括 '\0');
2:sizeof是一个取字节运算符,strlen是函数;
3:sizeof可以用类型做参数,strlen只能用 char * 做参数,且必须是 “\0”结尾的;
4:strlen的结果要在运行的时候才能计算出来(计算字符串的差长度),而sizeof,大部分编译程序在编译的时候就把sizeof计算出来了;
5:sizeof后面如果是类型的话,必须要加 ( ) ;如果是变量名的话,可以不加 ( ) ;因为sizeof只是一个操作符,而不是函数;
6:数组作为参数传递给函数时,传递的是指针,而不是数组,传递的是数组的首地址;
eg:fun(char[8]) ; fun(char[]) ; fun(char *) ; // 三者的作用是一样的,都是数组的首地址
eg:char * ss="0123456789";
sizeof(ss); //结果为4,ss是指向字符串常量的字符指针
sizeof(*ss) ; //结果为1,*ss是第一个字符 '0';为char类型;
strlen (ss) ;//结果为10,获取的是字符串的长度。
7:sizeof 操作符不能返回被动态分配的数组或外部数组的尺寸,也不能应用于函数类型、不完全类型(指具有未知存储大小数据的数据类型,如:未知存储大小的数组类型,未知内容的结构或联合类型)。