sizeof (1)

今天 帮一个同事调试他新写的一段代码, 说他只是正常的加了一个类。

然后对他进行初始化, 但是每次调用类的初始化之后,会发现原来的参数被变了,

而且程序老是crash.

 

一开始不知道 问题在哪里,请我帮忙 来看。

我先把类的初始化注释掉, 编译,执行没有问题, 正常。

 

那看起来应该是类的初始化有问题。

 

因为涉及到公司的保密, 所以简化如下,

 

因为 A的load里面, 他用了std::list的遍历, 但是是还是用的像原来的C语言的

std::list<>sl;

int len = sl.size();

std::list<>::iter bb=sl.begin;

for(int i=0;i<len;i++)

{

//其他的处理

....

  ++bb;

}

 

仔细看过,好像也没有问题啊。

 

再看这个类里面到底做了什么, 发现还有一个类B

 

简化如下 :

 

当时只是简单看了一下,没有注意到

再仔细一下,发现好像不对, sizeof应该不是这样用的。

本身 sizeof已经代表了你所占用的空间大小了。

 

所以把再多乘的那个sizeof(int) 去掉, 再编译执行, 就没有问题了。

 

 

问题是解决了, 那就把 sizeof再复习一下吧:

 

sizeof有三种语法形式,如下:

  1) sizeof( object ); // sizeof( 对象 );   

      2) sizeof( type_name ); // sizeof( 类型 );   

      3) sizeof object; // sizeof 对象;

 

sizeof也可以对一个函数调用求值,其结果是函数返回类型的大小,函数并不会被调用,我们来看一个完整的例子:

  

 

C99标准规定,函数、不能确定类型的表达式以及位域(bit-field)成员不能被计算sizeof值,即下面这些写法都是错误的:

  

 

3. sizeof的常量性   sizeof的计算发生在编译时刻,所以它可以被当作常量表达式使用,如:   char ary[ sizeof( int ) * 10 ]; // ok   最新的C99标准规定sizeof也可以在运行时刻进行计算,如下面的程序在Dev-C++ 中可以正确执行:   int n;   n = 10; // n动态赋值   char ary[n]; // C99也支持数组的动态定义   printf("%d/n", sizeof(ary)); // ok. 输出10

 

4. 基本数据类型的sizeof

  这里的基本数据类型指short、int、long、float、double这样的简单内置数据类型,由于它们都是和系统相关的,所以在不同的系统下取值可能不同,这务必引起我们的注意,尽量不要在这方面给自己程序的移植造成麻烦。   一般的,在32位编译环境中,sizeof(int)的取值为4。

 

5. 指针 变量的sizeof

  学过数据结构 的你应该知道指针是一个很重要的概念,它记录了另一个对象的地址。既然是来存放地址的,那么它当然等于计算机内部地址总线的宽度。所以在32位计算机中,一个指针变量的返回值必定是4(注意结果是以字节为单位),可以预计,在将来的64位 系统中指针变量的sizeof结果为8。

 

6. 数组的sizeof

  数组的sizeof值等于数组所占用的内存字节数,如:   

char a1[] = "abc";   

int a2[3];   

sizeof( a1 ); // 结果为4,字符 末尾还存在一个NULL终止符   

sizeof( a2 ); // 结果为3*4=12(依赖于int)   

一些朋友刚开始时把sizeof当作了求数组元素的个数,现在,你应该知道这是不对的,那么应该怎么求数组元素的个数呢Easy,通常有下面两种写法:   

int c1 = sizeof( a1 ) / sizeof( int ); // 总长度/单个元素的长度   

int c2 = sizeof( a1 ) / sizeof( a1[0] ); // 总长度/第一个元素的长度

 

 

7. 结构体的sizeof

  这是初学者问得最多的一个问题,所以这里有必要多费点笔墨。让我们先看一个结构体:   

struct S1   {   

char c;   

int i;   

};   

问sizeof(s1)等于多少聪明的你开始思考了,char占1个字节,int占4个字节,那么加起来就应该是5。

是这样吗你在你机器上试过了吗也许你是对的,但很可能你是错的!VC6中按默认设置得到的结果为8。

 

 

与strlen区别
  strlen(char*)函数求的是字符串的实际长度,它求得方法是从开始到遇到第一个'/0',如果你只定义没有给它赋初值,这个结果是不定的,它会从aa首地址一直找下去,直到遇到'/0'停止。   
char aa[10];cout<<strlen(aa)<<endl; //结果是不定的   
char aa[10]={'/0'};
cout<<strlen(aa)<<endl; //结果为0   
char aa[10]="jun";
cout<<strlen(aa)<<endl; //结果为3   
而sizeof()函数返回的是变量声明后所占的内存数,不是实际长度。   
sizeof(aa) 返回10   
int a[10];
sizeof(a) 返回40   
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   
sizeof返回对象所占用的字节大小. //正确   
strlen返回字符个数. //正确   
在使用sizeof时,有一个很特别的情况,就是数组名到指针蜕变,   
char Array[3] = {'0'};   
sizeof(Array) == 3;   
char *p = Array;   
strlen(p) == 1;//sizeof(p)结果为4   

在传递一个数组名到一个函数中时,它会完全退化为一个指针   ----------------------------------------------------------   

看完以上你是否很清楚sizeof和strlen的区别了呢?还不明白的话,我们看下面几个例子:  

 第一个例子  
char* ss = "0123456789";   
sizeof(ss) 结果 4 ===》ss是指向字符串常量的字符指针   
sizeof(*ss) 结果 1 ===》*ss是第一个字符   

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

大部分编译程序 在编译的时候就把sizeof计算过了 是类型或是变量的长度   
这就是sizeof(x)可以用来定义数组维数的原因  

第二个例子
char str[20]="0123456789";   
int a=strlen(str); //a=10;   
int b=sizeof(str); //而b=20;   
char ss[] = "0123456789";   
sizeof(ss) 结果 11 ===》ss是数组,计算到/0位置,因此是10+1   
sizeof(*ss) 结果 1 ===》*ss是第一个字符   
char ss[100] = "0123456789";   
sizeof(ss) 结果是100 ===》ss表示在内存中的大小 100×1   
strlen(ss) 结果是10 ===》strlen是个函数内部实现是用一个循环计算到/0为止之前   
int ss[100] = "0123456789";   
sizeof(ss) 结果 400 ===》ss表示在内存中的大小 100×4   
strlen(ss) 错误 ===》strlen的参数只能是char* 且必须是以'/0'结尾的   
char q[]="abc";   char p[]="a/n";   
sizeof(q),sizeof(p),strlen(q),strlen(p);   结果是 4 3 3 2   

第三个例子   
char szPath[MAX_PATH]   
如果在函数内这样定义,那么sizeof(szPath)将会是MAX_PATH,
但是将szPath作为虚参声明时(void fun(char szPath[MAX_PATH])),sizeof(szPath)却会是4(指针大小)   
char szPath[MAX_PATH]   
如果在函数内这样定义,那么sizeof(szPath)将会是MAX_PATH,
但是将szPath作为虚参声明时(void fun(char szPath[MAX_PATH])),sizeof(szPath)却会是4(指针大小)   

还有一位网友的说明也很好:   其实理解 sizeof 只需要抓住一个要点:栈   程序存储分布有三个区域:栈、静态和动态。能够从代码直接操作的对象,包括任何类型的变量、指针,都是在栈上的;
动态和静态存储区是靠栈上的指所有针间接操作的。

sizeof 操作符,计算的是对象在栈上的投影体积;记住这个就很多东西都很清楚了。   

char const * static_string = "Hello";   
sizeof(static_string) 是 sizeof 一个指针,所以在 32bit system 是 4   

char stack_string[] = "Hello";   sizeof(stack_string) 是 sizeof 一个数组,所以是 6 * sizeof(char)   

char * string = new char[6];   strncpy(string, "Hello", 6");   sizeof(string) 是 sizeof 一个指针,所以还是 4。

和第一个不同的是,这个指针指向了动态存储区而不是静态存储区。  

 不管指针指向的内容在什么地方,sizeof 得到的都是指针的栈大小   

C++ 中对引用的处理比较特殊;sizeof 一个引用得到的结果是 sizeof 一个被引用的对象的大小;

所以   
struct O   {   
int a, b, c, d, e, f, g, h;   
};   
int main()   {   
O & r = *new O;   
cout << sizeof(O) << endl; // 32   
cout << sizeof r << endl; // 也是 32   
system("PAUSE");   }   
r 引用的是整个的 O 对象而不是指向 O 的指针,所以 sizeof r 的结果和 sizeof O 完全相同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值