收藏了, 看了很多次, 印象还是不深刻, 这篇挺详细的, 转过来自己学习了。
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 。
strlen 计算长度时,计算 “/ 0” 结束符之前的字符个数, “/n” 算一个字符。
sizeof 计算字符串长度时计算所有字符个数 ( 结束符也算范围内 ),“/ 0” “/n” 都算一个字符。
一、 sizeof 的概念 sizeof 是 C 语言的一种单目操作符,如 C 语言的其他操作符 ++ 、 -- 等。它并不是函数。 sizeof 操作符以字节形式给出了其操作数的存储大小。操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型决定。其实可以简单的理解 sizeof 是征对 " 类型 " 的。
二、 sizeof 的使用方法
1 、用于数据类型 sizeof 使用形式: sizeof ( type ) 数据类型必须用括号括住。如 sizeof ( int )。
2 、用于变量
sizeof 使用形式: sizeof ( var_name )或 sizeof var_name
变量名可以不用括号括住。如 sizeof (var_name) , sizeof var_name 等都是正确形式。带括号的用法更普遍,大多数程序员采用这种形式。
注意: sizeof 操作符不能用于函数类型,不完全类型或位字段。不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、 void 类型等。
三、 sizeof 的结果
sizeof 操作符的结果类型是 size_t ,它在头文件中 typedef 为 unsigned int 类型。该类型保证能容纳实现所建立的最大对象的字节大小。
1 、若操作数具有类型 char 、 unsigned char 或 signed char ,其结果等于 1 。因为 ANSI C 正式规定字符类型为 1 字节。
2 、 int 、 unsigned int 、 short int ( short )、 unsigned short 、 long int ( long ) 、 unsigned long 、 float 、 double 、 long double 类型的 sizeof 在 ANSI C 中没有具体规定,大小依赖于实现,一般可能分别为 2 、 2 、 2 、 2 、 4 、 4 、 4 、 8 、 10 。
3 、当操作数是指针时, sizeof 依赖于编译器。例如 Microsoft C/C++7.0 中, near 类指针字节数为 2 , far 、 huge 类指针字节数为 4 。一般 Unix 的指针字节数为 4 。
4 、当操作数具有数组类型时,其结果是数组的总字节数,特别要注意字符串数组,如: Char str[]=“ 123456” sizeof(str)=7 。
5 、联合类型操作数的 sizeof 是其最大字节成员的字节数。结构类型操作数的 sizeof 是这种类型对象的总字节数,包括任何垫补在内。 让我们看如下结构: struct {char b; double x;} a; 在某些机器上 sizeof ( a ) =16 ,而一般 sizeof ( char ) + sizeof ( double ) =9 。 这是因为编译器在考虑对齐问题时,在结构中插入空位以控制各成员对象的地址对齐。
6 、如果操作数是函数中的数组形参或函数类型的形参, sizeof 给出其指针的大小。 即: int func(char p[100]) { sizeof(p) = 4; } C/C++ 中不能传数组 , 只能传指针 , 所以任何数组都会隐式转成指针形式进行操作 , 所以 " 类型 " 还是指针。
7 . sizeof 是运算符 当编译器编译时 会自动运算这个变量的大小的 并使用它的大小代替 sizeof 的值如 int len = sizeof(int); 编译时 编译器计算出 int 的大小 大小为 4 所以把上面这句变成 int len = 4
四、 sizeof 与其他操作符的关系 sizeof 的优先级为 2 级,比 / 、 % 等 3 级运算符优先级高。它可以与其他操作符一起组成表达式。如 i*sizeof ( int );其中 i 为 int 类型变量。
五、 sizeof 的主要用途
1 、 sizeof 操作符的一个主要用途是与存储分配和 I/O 系统那样的例程进行通信。例如: void *malloc ( size_t size ) , size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream) 。 2 、 sizeof 的另一个的主要用途是计算数组中元素的个数。例如: void *memset ( void *s,int c,sizeof(s) )。
3. 在动态分配一对象时 , 可以让系统知道要分配多少内存。
如: int *p=(int *)malloc(sizeof(int)*10);
4. 由于操作数的字节数在实现时可能出现变化,建议在涉及到操作数字节大小时用 sizeof 来代替常量计算。
5. 如果操作数是函数中的数组形参或函数类型的形参, sizeof 给出其指针的大小。
六、建议
由于操作数的字节数在实现时可能出现变化,建议在涉及到操作数字节大小时用 ziseof 来代替常量计算。
strlen ()
一、 strlen 是函数
strlen 只能用 char* 做参数,且必须是以 ''/0'' 结尾的。 Strlen 将返回它的长度,不包括 ‘/ 0’ 。
二、由几个例子说开去。
第一个例子: char* ss = "0123456789"; sizeof(ss) 结果 4 === >ss 是指向字符串常量的字符指针 sizeof(*ss) 结果 1 === >*ss 是第一个字符
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
第二个例子: class X{ int i; int j; char k; };
X x; cout<<sizeof(X)<<endl; 结果 12 === > 内存补齐 cout<<sizeof(x)<<endl; 结果 12 同上
第三个例子: 数组用作参数传递,见上面 6 列出几个重要的区别: 1.sizeof 是算符, strlen 是函数。 2.sizeof 可以用类型做参数, strlen 只能用 char* 做参数,且必须是以 ''/0'' 结尾的。 sizeof 还可以用函数做参数,比如: short f(); printf("%d/n", sizeof(f())); 输出的结果是 sizeof(short) ,即 2 。 3.strlen 计算的是字符串的长度, sizeof 计算的是变量使用的内存大小,不受里面存储的内容改变 4.strlen 的结果要在运行的时候才能计算出来,时用来计算字符串的长度,不是类型占内存的大小。 5.sizeof 后如果是类型必须加括弧,如果是变量名可以不加括弧。这是因为 sizeof 是个操作符不是个函数。 6. 当适用了于一个结构类型时或变量, sizeof 返回实际的大小, 当适用一静态地空间数组, sizeof 归还全部数组的尺寸。 sizeof 操作符不能返回动态地被分派了的数组或外部的数组的尺寸 。 6. 数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址,如: 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 的时候,通常是计算字符串数组的长度
好了看了上面的讲解和例题,我们来测试几个题:
1 .不要上机测试,否则便没有什么意义。
如下程序的输出是什么?(在 intel x86(32-bit) platform. ) #include <stdio.h> #include<stdlib.h> #include<string.h> int main( ) { char str[10]; char *p; memset(str,0x00,sizeof(str)); p = (char *)malloc(100); printf("%d/n",sizeof(p)); printf("%d/n",sizeof('p')); printf("%d/n",strlen(str)); exit(0); }
答: 4/1/0 , 如果不加 memset() ,第三行就会打出 15 (随机数),请问这是为什么? memset 函数是初始化分配的内存空间,使用 0 、 0x00 都是 0 ,即‘ /0' ,不同系统当分配一块内存时,这块内存中的内容是未知的,系统只是根据申请者的要求为其划一块内存并不管他原先的内容是什么(有的系统清零),所以你的是随即数 15 。
2 .你能够正确的说出它们的 sizeof 和 strlen 的大小吗?
#include <stdio.h> #include<stdlib.h> #include<string.h> int main( ) { char *str1="absde"; char str2[]="absde"; char str3[8]={'a',}; char str4[8]={'a','b','s','e','f','g','h','j'};
printf("sizeof(str1)=%d/n",sizeof(str1)); printf("sizeof(str2)=%d/n",sizeof(str2)); printf("sizeof(str3)=%d/n",sizeof(str3)); printf("sizeof(str4)=%d/n",sizeof(str4));
printf("strlen(str1)=%d/n",strlen(str1)); printf("strlen(str2)=%d/n",strlen(str2)); printf("strlen(str3)=%d/n",strlen(str3)); printf("strlen(str4)=%d/n",strlen(str4));
exit(0);
} 答: sizeof 是计算括号中变量的类型所占的储存空间 ( 不考虑内容 ) ; strlen 是计算变量值为起点的内存地址到第一个 '/0' 的距离,以字节为单位,字符串尾部为 '/0',0=='/0' (不包括 ’/ 0’ )。正确答案是: 4 、 6 、 8 、 8 ; 5 、 5 、 1 、 8 ;
可能这个是在 C 语言里面比较基础的问题了,但是很多情况下是经常混淆的,必须下面的一组数据,你能够正确的说出它们的 sizeof 和 strlen 的大小吗? char *str1="absde"; char str2[]="absde"; char str3[8]={'a',}; char str4[8]={'a','b','s','e','f','g','h','j'};
其实你只要掌握了两者的意义,就很容易解了,这种题目在笔试的时候最容易出了。答案见下面:
sizeof(str1)=4; sizeof(*str1)=1; strlen(str1)=5; sizeof(str2)=6; strlen(str2)=5; sizeof(str3)=8; strlen(str3)=1; sizeof(str4)=8; strlen(str4)=13; strlen(*str1) 出错 passing arg1 of 'strlen' makes pointer from integer without a cast.
sizeof 是计算括号中变量的类型所占的储存空间。 strlen(str4) 有可能为不小于 8 的其他数字,取决于内存中的数据,因为 strlen 是计算变量值为起点的内存地址到第一个 '%content%' 的距离,以字节为单位,字符串尾部为 '%content%',0=='%content%'.