一、Defintion:
sizeof返回一个对象或类型名的长度,返回值的类型为size_t,长度单位为字节。sizeof可用于求类的大小及求结构体的大小。
语法形式:
1 2 3 4 |
sizeof (typename) sizeof (expr) sizeof expr //expr可以不用加括号,sizeof更像一个特殊的宏,因其在编译阶段求值 //sizeof没有计算表达式expr的值,特别地,sizeof *p,指针p可以指向一个无效地址,无需对p作解引用操作 |
解释:
(1) 类型作参数 (2)变量作参数
(3)数组名作参数,计算值为编译器为数组分配的内存空间。
1 2 3 |
char str[]="12345"; int a1=sizeof(str); //a1=6 结尾有'\0'字符 int a[10]={1,2}; int a2=sizeof(a); //a2=40 char c[2][3]={"aa","bb"}; int a3=sizeof(c); //a3=6 |
(4)函数作参数,返回值为函数返回值所占用的内存空间(不必深究,无意义)
1 2 3 4 5 |
short f1(); int a1=sizeof(f1()); //a1=2;返回值调用sizeof,返回返回值的大小 int a2=sizeof *f1; //a2=2; *f2和f2()等价 int a2=sizeof(f1); //不能对函数名调用sizeof,因其大小在编译期间不确定 void f2(); int a3=sizeof(f2()); //错误 |
(5)指针作参数,返回指针所占的内存空间,一般为4个字节。这个概念有用!
指针是32位的物理地址,不管什么类型的指针,其大小为4.
1 2 3 4 5 6 7 8 9 10 |
char *str="1234"; int a1=sizeof(str) //a1=4; int a2=sizeof(*str); //指针指向的对象,a2=1; int x[10]; int *p=x; //指针可以指向一个无效地址 int a3=sizeof(x); //a3=40=10*4 int a4=sizeof(*x); //a4=4 int a5=sizeof(p); //a5=4 int a6=sizeof(*p); //a6=4 int *d= new int[10]; //动态指针 int a7=sizeof(d); //a7=4 |
(6)联合体(union)作参数
在一个联合内可以定义多种不同的数据类型,这些数据共享同一段内存,在不同的时间保存不同的数据类型和不同长度的变量,并且同一时间只能储存其中一个成员变量的值。 union的成员不可以为静态、引用等。
1 2 3 4 5 6 7 8 |
union foo{ union foo1{ int i; int i; char c; char c[10]; double k; double k; }; }; int a1=sizeof(foo); //a1=8; int a2=sizeof(foo1); //a2=16 |
这里涉及到字节对齐的问题。一个联合体被声明时,编译程序自动产生一个变量,其长度为联合体中最大的变量长度的整数倍。
结论:复合数据类型,如union,struct,class的对齐方式为成员中对齐方式最大的成员的对齐方式。
二、深入理解sizeof
参考自http://www.cnblogs.com/wanghetao/archive/2012/04/04/2431760.html
1 2 3 |
int a=0; cout<<sizeof(a=3)<<endl; //4 cout<<a<<endl; //a=0 |
1、sizeof在编译阶段处理, sizeof作用范围内,即()里面的内容也不能被编译,而是被替换成类型,=操作符返回左操作数的类型,所以a=3相当于int.
结论:sizeof是不可能支持链式表达式的,这是和一元操作符不同之处。
2、关于动态数组的深入
1 2 3 4 5 6 |
double *(*a) [3][6]; //指针a指向double*[3][6]类型的数组 int a1=sizeof(a); //a1=4; int a2=sizeof(*a); //3*6*sizeof(double *)=72 int a3=sizeof(**a); //**a表示一个double*[6]类型的数组,6*sizof(double *)=24 int a4=sizeof(***a); //***a表示double * 一个元素 int a5=sizeof(****a); //表示 double |
3、向函数传递数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include <iostream> using namespace std; int Sum(int i[]) //注意这里,传入的时一个int 型的指针 { int sumofi = 0; for (int j = 0; j < sizeof(i)/sizeof(int); j++) //实际上,sizeof(i) = 4 { sumofi += i[j]; } return sumofi; } int main() { int allAges[6] = {21, 22, 22, 19, 34, 12}; cout<<Sum(allAges)<<endl; system("pause"); return 0; } |
解决方法是使用指针或者引用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
int Sum(int (*i)[6]){ //i是一个指向 int[6]类型的指针 int sumofi = 0; for (int j = 0; j < sizeof(*i)/sizeof(int); j++) { sumofi += (*i)[j]; //sizeof(*i)=24 } return sumofi; } int main(){ int allAges[] = {21, 22, 22, 19, 34, 12}; cout<<Sum(&allAges)<<endl; system("pause"); return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
int Sum(int (&i)[6]){ int sumofi = 0; for (int j = 0; j < sizeof(i)/sizeof(int); j++){ sumofi += i[j]; } return sumofi; } int main(){ int allAges[] = {21, 22, 22, 19, 34, 12}; cout<<Sum(allAges)<<endl; system("pause"); return 0; } |
问题来了,这里传入数组的大小一定必须事先指明,那么这样也就失去了用sizeof计算数组大小的意义,所以需要一个额外的参数来说明数组的大小。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include <iostream> using namespace std; int Sum(int *i, unsigned int n){ int sumofi = 0; for (int j = 0; j < n; j++) { sumofi += i[j]; } return sumofi; } int main(){ int allAges[] = {21, 22, 22, 19, 34, 12}; cout<<Sum(allAges, sizeof(allAges)/sizeof(int))<<endl; system("pause"); return 0; } |