不见得你会计算C字符串长度
最近在看人工智能相关的知识,无意中发现了一个巨牛的 人工智能教程,分享一下给大家。
教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家。点 这里 可以直接看教程。
C 字符串
在 C 语言中,字符串实际上是使用字符 '\0'
终止的一维字符数组。
以下几种方式表示的都是 C 字符串的正确表达方式。
1 | // 要以 '\0' 结尾 |
看下面另外一种声明方式:
1 | char greeting[] = {'h', 'e', 'l', 'l', 'o'}; |
输出结果:
1 | greeting: hello\376 |
这个结果在不同编译器下面可能还会不一样,总之输出都不是我们想要的结果。这种方式创建的字符串没有 '\0'
,不算是真正的 C 字符串,所以建议大家在声明 C 字符串的时候使用字符指针(char *)的方式。
string.h
里面声明了很多关于操作 C 字符串的库函数。
字符串长度
这里在说计算字符串长度的前提是字符编码都是按照UTF-8(中文占用3个字节,英文占用1个字节)的编码形式为前提的。我们先来看下面这个例子,如下:
1 | char *greeting1 = "hello"; |
如果你能说出上面 printf
的结果,基本上关于计算字符串长度的问题就迎刃而解了。
按照 UTF-8 编码,上面例子的输出结果如下所示:
1 | greeting1 sizeOf: 8, strlen: 5 |
如果输出结果令你无法相信,可以选择继续往下看或者你自己写代码试试。
sizeof、strlen
在 linux.die 可以查到 strlen 的说明,如下:
1 | Synopsis: |
函数 strlen
返回字符串里的字符数,不包括终止字符 '\0'
,这里注意 strlen
是一个 C 的函数,而 sizeof
只是一个操作符。
我们知道,sizeof
操作符的参数可以是数组、指针、类型、对象、函数等,函数 strlen
的参数只能是字符串。
对于 sizeof
, 其参数不同时,其返回的值也不一样,如下:
1、数组:编译时分配的数组空间大小;
2、指针:存储该指针所用的空间大小(32位机器上是4,64位机器上是8);
3、类型:该类型所占的空间大小;
4、对象:对象的实际占用空间大小(这个指的是在 C++ 中);
5、函数:函数的返回类型所占的空间大小。函数的返回类型不能是 void 类型;
那我们再回头看看上面的例子,我把要说明的写在注释上面了。
1 | // 注意这里是指针 |
小结:
1、sizeof
是一个操作符,而 strlen
是 C 语言的库函数。
2、sizeof
的参数可以是任意数据类型或者表达式,而 strlen
只能以结尾为 '\0'
的字符串作参数。
3、sizeof
的结果在编译时就计算出了,而 strlen
必须在运行时才能计算出来。
4、sizeof
计算数据类型占内存的大小,strlen
计算字符串实际长度,要记住 strlen
计算出来的结果不包括结束符 '\0'
。
5、sizeof
反应的并非真实字符串长度而是所占空间大小,所以memset
初始化字符串的时候用 sizeof
较好。
6、系统函数返回值是 char *
(字符指针)类型的会在末尾加上结束符 '\0'
。
7、无论是 sizeof
还是 strlen
计算结果的单位都是字节。
我们还需要注意一点,strlen
函数,当数组名作为参数传入时,实际上数组就退化成指针了。举个例子,如下图所示:
可以看出传入进来的参数会被退化为指针。
探索无止境
在文章的开始,我给出了几种 C 字符串的正确表达方式,那我们再来看另外一种。
1 | char greeting[4] = "blog"; |
这种方式看起来好像很完美的样子,其实是不对的,写个例子给大家,如下:
1 | int main(int argc, const char *argv[]) |
编译运行,结果如下:
1 | greeting len: 10 |
苍天呀,这结果让人无语。。。
对于 char greeting[4] = "blog"
其实是定义一个长度为 4 的字符数组,但是字符串 "blog"
实际是要包括结束符 \0
的,也就是说下面的代码
1 | char greeting[4] = "blog"; |
本质和下面代码是一样的,如下:
1 | char greeting[] = {'b', 'l', 'o', 'g'}; |
显然是不正确的,那我们修改一下代码,如下:
1 | int main(int argc, const char *argv[]) |
或者这样写:
1 | int main(int argc, const char *argv[]) |
这样修改后,再编译运行结果就对了,如下:
1 | greeting len: 4 |
我们知道的东西是有限的,我们不知道的东西则是无穷的。