浅析strlen()和sizeof()

来源:互联网 发布:网络市场中间商的类型 编辑:程序博客网 时间:2024/05/24 05:59

  在 C 语言的学习及找工作时的笔试中,经常会遇到strlen()和 sizeof()这一对让人傻傻分不清的双胞胎。那么这对双胞胎有什么区别呢?
  1. strlen()求的是字符串的有效长度,针对的对象是字符串;sizeof()求的是大小,针对的是类型。
  2. strlen()是函数,而 sizeof()表面看起来是函数,其本质是关键字。
  首先先明确 strlen()是一个函数,而 sizeof()是一个关键字,何以表明?

#include<stdio.h>void fun(){printf(“This is fun()!\n”);} void main(){fun();}

这里写图片描述
  fun 是一个函数,则在调用函数时,函数名一定要加上括号,即使函数没有任何参数,如果不加括号,则无法调动函数的运算。

#include<stdio.h>void fun(){    printf("this is fun\n");} void main(){    fun; //此处虽然不会造成程序编译错误,但不能调动函数 fun()的运行}

这里写图片描述
  在这个程序中,主函数中的fun表示的是函数fun()的地址,所以函数可以正常变异,但不能调动函数fun()。
  若一个名字代表的是函数名,则在调用函数时一定要加上括号,那么sizeof()关键字又有哪些特性,是否跟函数一样,计算大小时是否一定要加上括号?

#include<stdio.h>void main(){    int v = 10;    printf("%d\n", sizeof(v)); //1    printf("%d\n", sizeof v); //2    printf("%d\n", sizeof(10)); //3    printf("%d\n", sizeof 10); //4    printf("%d\n", sizeof(int)); //5    //printf("%d\n",sizeof int); //6 不能编译通过}

这里写图片描述
  从以上的程序运行角度看, 1,2,3,4,5 均能正常运行,并正确计算出其类型的大小,说明sizeof()在运行时可以不用(),这就从侧面说明了sizeof()不是一个函数,而是一个关键字。那么为什么 6 号语句不能编译通过?这是因为 sizeof 和 int 都是关键字,则 sizeof int 这样的写法相当于关键字的组合,形如 unsigned int 之类的组合,但并不是所有的关键字都能随意组合,所以此处出错。所以在使用 sizeof 关键字时,最好把括号加上,这样在其可读性和正确性上都会大大的提升。只不过,我们一定要记住, sizeof()不是函数,而是关键字。
  下面我们着重讨论两者在计算其长度与大小时的各种情况。

下面我们着重讨论两者在计算其长度与大小时的各种情况。

1.

#include<stdio.h>#include<string.h>void main(){    char str[] = "hello C"; //注, hello 与 C 之间有一空格    printf("strlen = %d\n", strlen(str));    printf("sizeof = %d\n", sizeof(str));}

运行结果:
这里写图片描述
解析:strlen()计算的是字符串的有效长度,即不包含’\0’的长度, sizeof()计算的是类型所占内存空间的大小(以字节为单位),对于字符串来说,要包含’\0’所占的空间,即 char str[]是一个数组,其大小为字符串”hello C”所占空间大小,注意的是,每个字符串末尾会有一个’\0’的结束标记,也会占用其存储空间。
2.

#include<stdio.h>#include<string.h>void main(){    char str[10] = "hello C";    printf("strlen = %d\n", strlen(str));    printf("sizeof = %d\n", sizeof(str));}

运行结果:
这里写图片描述
解析:char str[10]所定义的数组,空间大小确定, strlen()求其字符串的有效长度,而 sizeof()求的数组 str 的大小,虽说字符串长度为 7,但是空间大小却是 10 个字节。
3.

#include<stdio.h>#include<string.h>void main(){    char str[] = { 'h','e','l','l','c',' ','C' };    printf("strlen = %d\n", strlen(str));    printf("sizeof = %d\n", sizeof(str));}

运行结果:
这里写图片描述
解析:char str[]所定义的数组,其空间大小由所给的字符个数确定, strlen()求其字符串的有效长度,此处的 12 是随机值,其长度的大小在不同的环境下会有所不一样,原因是字符串的结束标记’\0’出现的位置是不确定的。换句话说, char str[] = {‘h’,’e’,’l’,’l’,’c’,”,’C’};这种定义方式是不会自动在数组之后加上’\0’的,因此字符串何时结束也就不得而知,而 sizeof()求数组 str 的大小,虽说字符串长度不确定,但由于使用了 7个字符对数组进行初始化,所以数组的大小空间为 7 字节。
4.

#include<stdio.h>#include<string.h>void main(){    char str[10] = { 'h','e','l','l','c',' ','C' };    printf("strlen = %d\n", strlen(str));    printf("sizeof = %d\n", sizeof(str));}

运行结果:
这里写图片描述
解析: char str[10]所定义的数组,其空间大小确定, 10 个字节, strlen()求其字符串的有效长度,此处为 7 个字节是固定值,或许你会问,没有’\0’的结束标记啊,为什么不是随机值了?这要求我们要对数组的初始化工作有所了解,数组 str 具有 10 个字节的空间,但未完全初始化,则剩余空间以 0 填充,其实’\0’的本质就是数字 0,所以 C 字符之后出现了数字 0,因此其字符串长度也就确定了, sizeof()计算数组 str 的大小则固定为10 个字节。
5.

#include<stdio.h>#include<string.h>void main(){    char str[] = { 'h','e','l','\0','l','c',' ','C' };    printf("strlen = %d\n", strlen(str));    printf("sizeof = %d\n", sizeof(str));}

运行结果:
这里写图片描述
解析:在数组的第 4 个位置给出了’\0’,字符’\0’的出现则意味着字符串的结束,所以长度为 3 个字节,而大小则为字符个数。
6.

#include<stdio.h>#include<string.h>void main(){    char str[] = { 'h','e','l','0','l','c',' ','C' };    printf("strlen = %d\n", strlen(str));    printf("sizeof = %d\n", sizeof(str));}

运行结果:
这里写图片描述
解析:在数组的第 4 个位置给出了’0’,字符’0’并不等价于‘’\0’,所以字符’0’不能作为字符串的结束位置,由于’\0’位置不能确定,因此其长度为随机值,大小仍为初始字符个数。
7.

#include<stdio.h>#include<string.h>void main(){    char str[] = { 'h','e','l',0,'l','c',' ','C' };     printf("strlen = %d\n", strlen(str));    printf("sizeof = %d\n", sizeof(str));}

运行结果:
这里写图片描述
解析:在数组的第 4 个位置给出了数字 0,发现字符串长度为 3,说明’\0’的本质就是数字 0,其实’\0’中的斜杠就是起到转义的作用,即’0’这样只能代表这是一个字符 0,而’\0’则认为不要把 0 当做一个字符看待,转义之后当做数字 0 看待,所以’\0’,其本质就是数字 0,这个观点很重要。
8.

#include<stdio.h>#include<string.h>void main(){    char str[10];    printf("strlen = %d\n", strlen(str));    printf("sizeof = %d\n", sizeof(str));}

运行结果:
这里写图片描述
解析:数组 str 未初始化,其内容为随机值,因此字符串的结束标记’\0’出现的位置不能确定,所以长度为随机值,但数组空间大小确定,为下标值 10。
9.

#include<stdio.h>#include<string.h>char str[10];void main(){    printf("strlen = %d\n", strlen(str));    printf("sizeof = %d\n", sizeof(str));}

运行结果:
这里写图片描述
解析:数组 str 定义为全局数组,局部数组未初始化时,内部数据为随机值,而全局数组未初始化时,其值用数字 0 填充,因此,相当于在第一个空间就出现了’\0’,所以长度为 0,其数组的大小为 10 字节。主要把握住数据会因为所处的生存作用域的不同,从而导致初始化的值不同。
10.

#include<stdio.h>#include<string.h>void main(){    char *str = "hello C";    printf("strlen = %d\n", strlen(str));    printf("sizeof = %d\n", sizeof(str));}

运行结果:
这里写图片描述
解析:长度就是字符串的有效长度,但大小不能是字符串的大小。sizeof()计算的是类型的大小,此处的类型为 char *str(字符指针类型),在 32 位的系统下,只要是指针,其大小都是 4 个字节。注意跟 char str[10]区别开来,这是数组类型,而 char *str是指针类型。
11.

#include<stdio.h>#include<string.h>void main(){    char *str[3] = { { "hello C" },{ "hello Cpp" },{ "hello Java" } };    printf("strlen = %d\n", strlen(*str));    printf("sizeof = %d\n", sizeof(str));}

运行结果:
这里写图片描述
解析:strlen(str)所求的是第一个字符串的长度,而 sizeof(str)所求的大小不能是 4字节,这是最容易上当的一个陷阱,很多人一旦看到*,心里就开始激动,认为 str 就是一个指针,从而大小是 4 字节,这就出错了,其实 char *str[3]真实的本质是一个数组,只不过每个元素存放的是字符指针而已,所以 sizoef(str)所求的大小应该是数组的大小,数组具有 3 个元素,每个元素是一个字符指针,因此其大小为 12 字节。总结:strlen()与 sizeof()在某些时候容易造成混淆,一般来说, strlen()是针对字符串求长度,并且只能是有效长度,即不包含反斜杠零’\0’的长度,如何确定字符串的长度大小,就看’\0’出现的位置, ’\0’是字符串的终结者,而 sizeof()是一个关键字,所计算的是类型的所占空间的大小, sizeof()计算的关键是能够正确区分所求类型。
  总结:strlen()与 sizeof()在某些时候容易造成混淆,一般来说, strlen()是针对字符串求长度,并且只能是有效长度,即不包含反斜杠零’\0’的长度,如何确定字符串的长度大小,就看’\0’出现的位置, ’\0’是字符串的终结者,而 sizeof()是一个关键字,所计算的是类型的所占空间的大小, sizeof()计算的关键是能够正确区分所求类型。

原创粉丝点击