打印
[牛人杂谈]

sizeof函数总结

[复制链接]
484|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yiyigirl2014|  楼主 | 2016-7-23 21:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
sizeof函数功能:计算数据空间的字节数
1.与strlen()比较
strlen计算字符数组的字符数,以""为结束判断,不计算为''的数组元素。
sizeof计算数据(包括数组、变量、类型、结构体等)所占内存空间,用字节数表示(当然用在字符数组计算""的大小)。
2.指针与静态数组的sizeof操作
指针均可看为变量类型的一种。所有指针变量的sizeof 操作结果均为4。
实例1::char *p;
sizeof(p)=4;
sizeof(*p) = 1;   //相当于sizeof(char);  
实例2:  
对于静态数组,sizeof可直接计算数组大小;
例:int a[10];
char b[]="hello";
sizeof(a)等于4*10=40;
sizeof(b)等于6;
void  fun(char p[])
{
sizeof(p);         //等于4,数组做型参时,数组名称当作指针使用!!
}
实例3(经典考题):
double* (*a)[3][6];
cout<<sizeof(a)<<endl; 4="" a为指针
cout<<sizeof(*a)<<endl; 72="" *a为一个有3*6个指针元素的数组
cout<<sizeof(**a)<<endl; 24="" **a为数组一维的6个指针
cout<<sizeof(***a)<<endl; 4="" ***a为一维的第一个指针
cout<<sizeof(****a)<<endl; 8="" ****a为一个double变量
问题解析:
a是一个很奇怪的定义,他表示一个指向double*[3][6]类型数组的指针。既然是指针,所以sizeof(a)就是4。
既然a是执行double*[3][6]类型的指针,*a就表示一个double*[3][6]的多维数组类型,因此sizeof(*a)=3*6*sizeof(double*)=72。
同样的,**a表示一个double*[6]类型的数组,sizeof(**a)=6*sizeof  (double*)=24。
***a就表示其中的一个元素,也就是double*了,所以sizeof(***a)=4。
****a,就是一个double了,所以sizeof(****a)=sizeof(double)=8。
3.格式的写法
sizeof操作符,对变量或对象可以不加括号,但若是类型,须加括号。
4.使用sizeof时string的注意事项
string s="hello";
sizeof(s)等于string类的大小(32),sizeof(s.c_str())得到的是与字符串长度(4)。
5.union 与struct的空间计算

</sizeof(****a)<</sizeof(***a)<</sizeof(**a)<</sizeof(*a)<</sizeof(a)<
沙发
yiyigirl2014|  楼主 | 2016-7-23 21:16 | 只看该作者
总体上遵循两个原则:
(1)整体空间是占用空间最大的成员(类型)所占字节的整数倍
(2)数据对齐原则----数据在内存中按照结构成员先后顺序进行排序,当排到该成员变量时,其前面已摆放的空间大小必须是该成员类型大小的整倍数,如果不够则补齐,以此向后类推。。。。。
注意:数组按照单个变量一个一个的摆放,而不是看成整体。如果成员中有自定义的类、结构体,也要注意数组问题。
实例4:[引用其他帖子的内容]
因为对齐问题使结构体的sizeof变得比较复杂,看下面的例子:(默认对齐方式下)
struct s1
{
char a;
double b;
int c;
char d;
};
struct s2
{
char a;
char b;
int c;
double d;
};
cout<<sizeof(s1)<<endl; // 24
cout<<sizeof(s2)<<endl; // 16
同样是两个char类型,一个int类型,一个double类型,但是因为对齐问题,导致他们的大小不同。计算结构体大小可以采用元素摆放法,我举例子说明一下:首先,CPU判断结构体的对界,根据上一节的结论,s1和s2的对界都取最大的元素类型,也就是double类型的对界8。然后开始摆放每个元素。
对于s1,首先把a放到8的对界,假定是0,此时下一个空闲的地址是1,但是下一个元素b是double类型,要放到8的对界上,离1最接近的地址是8了,所以b被放在了8,此时下一个空闲地址变成了16,下一个元素c的对界是4,16可以满足,所以c放在了16,此时下一个空闲地址变成了20,下一个元素d需要对界1,也正好落在对界上,所以d放在了20,结构体在地址21处结束。由于s1的大小需要是8的倍数,所以21-23的空间被保留,s1的大小变成了24。
对于s2,首先把a放到8的对界,假定是0,此时下一个空闲地址是1,下一个元素的对界也是1,所以b摆放在1,下一个空闲地址变成了2;下一个元素c的对界是4,所以取离2最近的地址4摆放c,下一个空闲地址变成了8,下一个元素d的对界是8,所以d摆放在8,所有元素摆放完毕,结构体在15处结束,占用总空间为16,正好是8的倍数。
这里有个陷阱,对于结构体中的结构体成员,不要认为它的对齐方式就是他的大小,看下面的例子:
实例5:
struct s1
{
char a[8];
};
struct s2
{
double d;
};
struct s3
{
s1 s;
char a;
};
struct s4
{
s2 s;
char a;
};
cout<<sizeof(s1)<<endl; // 8
cout<<sizeof(s2)<<endl; // 8
cout<<sizeof(s3)<<endl; // 9
cout<<sizeof(s4)<<endl; // 16;
s1和s2大小虽然都是8,但是s1的对齐方式是1,s2是8(double),所以在s3和s4中才有这样的差异。
所以,在自己定义结构体的时候,如果空间紧张的话,最好考虑对齐因素来排列结构体里的元素。
   相关常数:
   sizeof int:4
   sizeof short:2
   sizeof long:4
   sizeof float:4
   sizeof double:8
   sizeof char:1
   sizeof p:4
   sizeof WORD:2
   sizeof DWORD:4

使用特权

评论回复
板凳
wahahaheihei| | 2016-7-23 23:10 | 只看该作者
sizeof(类型说明符,数组名或表达式);
或sizeof 变量名;

使用特权

评论回复
地板
wahahaheihei| | 2016-7-23 23:11 | 只看该作者
sizeof是C/C++中的一个操作符(operator),简单的说其作用就是返回一个对象或者类型所占的内存字节数。
MSDN上的解释为:
The sizeof keyword gives the amount of storage, in bytes, associated with a variable or a type(including aggregate types). This keyword returns a value of type size_t.
其返回值类型为size_t,在头文件stddef.h中定义。这是一个依赖于编译系统的值,一般定义为
1
typedef unsigned int size_t;
世上编译器林林总总,但作为一个规范,它们都会保证char、signed char和unsigned
char的sizeof值为1,毕竟char是我们编程能用的最小数据类型。

使用特权

评论回复
5
wahahaheihei| | 2016-7-23 23:11 | 只看该作者
语法
sizeof有三种语法形式,如下:

sizeof(object);//sizeof(对象);
sizeof(type_name);//sizeof(类型);
sizeofobject;//sizeof对象;
所以,

int i;
sizeof(i);//ok
sizeof i;//ok
sizeof(int);//ok
sizeofint;//error

使用特权

评论回复
6
wahahaheihei| | 2016-7-23 23:12 | 只看该作者
Sizeof与Strlen的区别与联系(转)

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

2.sizeof是算符,strlen是函数。

3.sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以''\0''结尾的。
sizeof还可以用函数做参数,比如:
short f();
printf("%d\n", sizeof(f()));
输出的结果是sizeof(short),即2。

4.数组做sizeof的参数不退化,传递给strlen就退化为指针了。

5.大部分编译程序 在编译的时候就把sizeof计算过了 是类型或是变量的长度这就是sizeof(x)可以用来定义数组维数的原因
char str[20]="0123456789";
int a=strlen(str); //a=10;
int b=sizeof(str); //而b=20;

6.strlen的结果要在运行的时候才能计算出来,时用来计算字符串的长度,不是类型占内存的大小。

7.sizeof后如果是类型必须加括弧,如果是变量名可以不加括弧。这是因为sizeof是个操作符不是个函数。

8.当适用了于一个结构类型时或变量, sizeof 返回实际的大小,
当适用一静态地空间数组, sizeof 归还全部数组的尺寸。
sizeof 操作符不能返回动态地被分派了的数组或外部的数组的尺寸

9.数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址,
如:
fun(char [8])
fun(char [])
都等价于 fun(char *)
在C++里参数传递数组永远都是传递指向数组首元素的指针,编译器不知道数组的大小
如果想在函数内知道数组的大小, 需要这样做:
进入函数后用memcpy拷贝出来,长度由另一个形参传进去
fun(unsiged char *p1, int len)
{
  unsigned char* buf = new unsigned char[len+1]
  memcpy(buf, p1, len);
}

我们能常在用到 sizeof 和 strlen 的时候,通常是计算字符串数组的长度
看了上面的详细解释,发现两者的使用还是有区别的,从这个例子可以看得很清楚:

char str[20]="0123456789";
int a=strlen(str); //a=10; >>>> strlen 计算字符串的长度,以结束符 0x00 为字符串结束。
int b=sizeof(str); //而b=20; >>>> sizeof 计算的则是分配的数组 str[20] 所占的内存空间的大小,不受里面存储的内容改变。  

上面是对静态数组处理的结果,如果是对指针,结果就不一样了

char* ss = "0123456789";
sizeof(ss) 结果 4 ===》ss是指向字符串常量的字符指针,sizeof 获得的是一个指针的之所占的空间,应该是

长整型的,所以是4
sizeof(*ss) 结果 1 ===》*ss是第一个字符 其实就是获得了字符串的第一位'0' 所占的内存空间,是char类

型的,占了 1 位

strlen(ss)= 10 >>>> 如果要获得这个字符串的长度,则一定要使用 strlen

使用特权

评论回复
7
734774645| | 2016-7-24 13:53 | 只看该作者
这些东西在确定长度方面非常方便。

使用特权

评论回复
8
734774645| | 2016-7-24 13:54 | 只看该作者
另外就是那个字符串不是有结束符吗,结束符会不会作为字符。

使用特权

评论回复
9
huangcunxiake| | 2016-7-24 16:31 | 只看该作者
指针的操作不知道是读取的什么。

使用特权

评论回复
10
zhuomuniao110| | 2016-7-24 16:51 | 只看该作者
a是一个很奇怪的定义,他表示一个指向double*[3][6]类型数组的指针。既然是指针,所以sizeof(a)就是4。

使用特权

评论回复
11
yiyigirl2014|  楼主 | 2016-7-27 19:00 | 只看该作者
多使用几次就熟悉的

使用特权

评论回复
12
稳稳の幸福| | 2016-7-27 21:49 | 只看该作者
不知道可以计算指针的长度不

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

207

主题

3516

帖子

10

粉丝