sizeof和strlen区别和使用方法

来源:互联网 发布:南风知我意txt微盘 编辑:程序博客网 时间:2024/05/01 01:20

一、sizeof的概念
  sizeofC语言的一种单目操作符,如C语言的其他操作符++--等。它并不是函数。sizeof操作符以字节形式给出了其操作数的存储大小。操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型决定。

二、sizeof的使用方法

  1、用于数据类型  

sizeof使用形式:sizeoftype

数据类型必须用括号括住。如sizeofint)。

2、用于变量

  sizeof使用形式:sizeofvar_name)或sizeof var_name

  变量名可以不用括号括住。如sizeof (var_name)sizeof var_name等都是正确形式。带括号的用法更普遍,大多数程序员采用这种形式。

  注意:sizeof操作符不能用于函数类型,不完全类型或位字段。不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。
  如sizeof(max)若此时变量max定义为int max(),sizeof(char_v) 若此时char_v定义为char char_v [MAX]MAX未知,sizeof(void)都不是正确形式。

三、sizeof的结果
  sizeof操作符的结果类型是size_t,它在头文件<stddef.h>typedefunsigned int类型。该类型保证能容纳实现所建立的最大对象的字节大小。
  1、若操作数具有类型charunsigned charsigned char,其结果等于1
  ANSI C正式规定字符类型为1字节。
  2intunsigned int short intunsigned short long int unsigned long floatdoublelong double类型的sizeof ANSI C中没有具体规定,大小依赖于实现,一般可能分别为2222444810
  3当操作数是指针时,sizeof依赖于编译器。例如Microsoft C/C++7.0中,near类指针字节数为2farhuge类指针字节数为4。一般Unix指针字节数为4
  4当操作数具有数组类型时,其结果是数组的总字节数。
  5联合类型操作数的sizeof是其最大字节成员的字节数。结构类型操作数的sizeof是这种类型对象的总字节数,包括任何垫补在内。
  让我们看如下结构:
  struct {char b; double x;} a;
  在某些机器上sizeofa=12,而一般sizeofchar+ sizeofdouble=9
  这是因为编译器在考虑对齐问题时,在结构中插入空位以控制各成员对象的地址对齐。如double类型的结构成员x要放在被4整除的地址。
  6如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小
四、sizeof与其他操作符的关系
  sizeof的优先级为2级,比/%3级运算符优先级高。它可以与其他操作符一起组成表达式。如i*sizeofint);其中iint类型变量。
五、sizeof的主要用途
  1sizeof操作符的一个主要用途是与存储分配和I/O系统那样的例程进行通信。例如:
  void *mallocsize_t size,
  size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream)
  2sizeof的另一个的主要用途是计算数组中元素的个数。例如:
  void * memsetvoid * s,int c,sizeof(s))。
六、建议
  由于操作数的字节数在实现时可能出现变化,建议在涉及到操作数字节大小时用ziseof来代替常量计算。

七、举例

由几个例子说开去。

第一个例子:

char* ss = "0123456789";

sizeof(ss) 结果 4 ===》ss是指向字符串常量的字符指针

sizeof(*ss) 结果 1 ===》*ss是第一个字符

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

 

char ss[] = "0123456789";

sizeof(ss) 结果 11 ===》ss是数组,计算到/0位置,因此是101

sizeof(*ss) 结果 1 ===》*ss是第一个字符

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

 

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*

 

第二个例子:

class X

{

               int i;

               int j;

               char k;

};

X x;

cout<<sizeof(X)<<endl; 结果 12 ===》内存补齐

cout<<sizeof(x)<<endl; 结果 12 同上

 

第三个例子:

char szPath[MAX_PATH]

如果在函数内这样定义,那么sizeof(szPath)将会是MAX_PATH

但是将szPath作为虚参声明时(void fun(char szPath[MAX_PATH]),sizeof(szPath)却会是4(指针大小)
八、sizeof深入理解。

1.sizeof操作符的结果类型是size_t,它在头文件中typedefunsigned 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);

}

有关内容见: C++ PRIMER?

我们能常在用到 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.

10.计算结构变量的大小就必须讨论数据对齐问题。为了CPU存取的速度最快(这同CPU取数操作有关,详细的介绍可以参考一些计算机原理方面的书),C++在处理数据时经常把结构变量中的成员的大小按照48的倍数计算,这就叫数据对齐(data alignment)。这样做可能会浪费一些内存,但理论上速度快了。当然这样的设置会在读写一些别的应用程序生成的数据文件或交换数据时带来不便。MS VC++中的对齐设定,有时候sizeof得到的与实际不等。一般在VC++中加上#pragma pack(n)的设定即可.或者如果要按字节存储,而不进行数据对齐,可以在Options对话框中修改Advanced compiler页中的Data alignment为按字节对齐。

11.sizeof操作符不能用于函数类型,不完全类型或位字段。不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。如sizeof(max)若此时变量max定义为int max(),sizeof(char_v) 若此时char_v定义为char char_v [MAX]MAX未知,sizeof(void)都不是正确形式

九、结束语
sizeof
使用场合。

1.sizeof操作符的一个主要用途是与存储分配和I/O系统那样的例程进行通信。例如: 

              void *mallocsize_t size, 

              size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream)

2.用它可以看看一类型的对象在内存中所占的单元字节。

void * memsetvoid * s,int c,sizeof(s)

3.在动态分配一对象时,可以让系统知道要分配多少内存。

4.便于一些类型的扩充,windows中就有很多结构内型就有一个专用的字段是用来放该类型的字节大小。

5.由于操作数的字节数在实现时可能出现变化,建议在涉及到操作数字节大小时用sizeof来代替常量计算。

6.如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小。

  strlen与sizeof的使用区别,是笔试中常考的也是易混淆的C语言基础知识。
  1.从功能定义上,strlen函数,用来求字符串的长度,sizeof函数是用来求指定变量或变量类型等所占用内存的大小;
  2.sizeof是运算符,而strlen是C库函数strlen只能用char*做参数,且以'/0'结尾的;
  对于静态数组处理:
     char str[20]="0123456789";
     strlen(str)=10;   //表示数组中字符串的长度
     sizeof(str)=20;   //表示数组变量分配的长度
  对于指针处理:
     char *str="0123456789";
     strlen(str)=10;     //表示字符串的长度
     sizeof(str)=4;      //表示指针变量的所占内存大小
     sizeof(*str)=1;     //表示'0'这个字符变量的所占内存大小
十 常用例子
首先我们声明了
char a[5];
a[0]='a';
a[1]='b';
a[2]='c';
1. sizeof()是计算参数所占用的内存的单元数(字节数),那么sizeof(a)==5;sizeof(*a)==1;另外sizeof("abc")==4(不是3)我想这个很容易明白。
2. strlen(const char *),此函数在msdn里面的解释:returns the number of characters in string, excluding the terminal NULL. No return value is reserved to indicate an error。如果直接翻译,其实我测试的结果是一致的(msdn当然还是应该相信的),问题在于:它说的不够清楚,它的意思是说返回字符串的字符个数,不包括结束符NULL(参数要求是以NULL结束的字符串,我的理解应该还包括'/0'结束的)。
3. 我觉得正确的理解是,strlen()是返回字符个数,且,这个个数应该是遇到null或'/0'之前的字符个数。
我们来测试:
#include <iostream.h>
#include <string.h>
void main ()
{   
  char a[5] ;
 a[0]='a';
 a[1]='c';
 a[2]='/0';
 a[3]='a';
 a[4]='b';
 cout <<sizeof(a)<<endl;
 cout<<strlen(a)<<endl;
 cout <<sizeof("abc")<<endl;
 cout <<strlen("abc/0d")<<endl;
}
结果为
5
2
4
3
例子-----------------------------------------------------------------------

 char s1[]="";
 char s2[]="Hello world!";
 char *p = s2;
 char *q = s1;
 char *r = (char *)malloc(100);
 char str1[]="123456789";
 char *a[]={"123","asdfsdf","0kle3340j"};
 
 char s3[10]={'m','o','b','i','l'};
 char s4[20]={'A','N','S','I','/0','C','+','+'};
 char s5[8]={'I','S','O','C','+','+','M'};

 int i;
 int j = 10;
 float f;
 float k=12.45;
 long l;
 double d;

void func(char str[100])
{
 printf("sizeof---str=%d/n",sizeof(str));
}

int tenof(char par)
{
 return par*10;
}

func(str);

printf("tenof(100)=%d",tenof(100));
printf("tenof(127)=%d",tenof(127));
printf("tenof(128)=%d",tenof(128));
printf("tenof('i')=%d",tenof('i'));

=========================================

sizeof(s1)=1
sizeof(s2)=13
sizeof(p)=4          //s2的首地址值的字节数是4位
sizeof(q)=4
sizeof(r)=4
sizeof(str)=4       //如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小

strlen(s3)=5
strlen(s4)=4
strlen(s5)=7

sizeof(i)=4          //int型变量的地址字节数是4位
sizeof(j)=4
sizeof(f)=4
sizeof(k)=4
sizeof(l)=4
sizeof(d)=8          //double型变量的地址字节数是8位

sizeof(a)=12    // 对数组做sizeof操作等效于对其元素类型做sizeof操作的结果乘上数组元素的个数。


sizeof(a[0])=4
sizeof(a[1])=4
sizeof(a[2])=4

 

 

sizeof---str=4
tenof(100)=1000
tenof(127)=1270
tenof(128)=-1280    //ASCII 编码只有 000~127 是标准的
tenof('i')=1050     //'A'=65,'a'=97, 'i'=105