漫谈:C、C++字符串的困局

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。


        由于历史的原因,C、C++字符串是个很让程序员头疼的东西。

目录

字符不是字符串,字符数组也不是字符串

字符串是字符数组,但字符串长度不是字符数组长度

void *不是char *,但你只能定义char[]

你以为char *就是字符串,其实不是

str函数不保证结束符

概念完整性


字符不是字符串,字符数组也不是字符串

        字符串被解读为字符数组,但是又不等价于字符数组,而是带有附加的结束符的字符数组。

    char c;//这是一个字符
    char cc[2] = {'a','b'};//这是两个字符的字符数组,但是不是字符串
    char ccc[3] = { 'a','b','\0' };//这是一个正确的字符串,但strlen长度是2不是3
    char str[2];//这是字符数组,长度为2,准备接收字符串
    strcpy(str, "ab");//这个字符串strlen长度为2,但是溢出了

字符串是字符数组,但字符串长度不是字符数组长度

        结束符‘\0’也是一个字符,但是又不计算在字符串长度里面(strlen)。

void *不是char *,但你只能定义char[]

        表达原始内存我们用void*,但是你不能定义void[],你只能定义char[]。现代语言解决了这个问题,把原始内存用BYTE来表达。

你以为char *就是字符串,其实不是

        由于这种混淆,我们自己写的函数的char*参数经常要求的并不是一个字符串,并不要求一定有结束符。系统库严谨一些,原始内存用void*做参数。

    char buf[256];
    char const* a = "1234567";
    memcpy(buf, a, 2);

	std::cout << buf << std::endl;//这里错了,buf里面没有字符串结束符

        内存复制函数一般也用char*做参数,经常会有人犯错,发现内存复制后的内容输出的时候后面多了一些乱码,这其实就是因为这个char*后面没有结束符。用memcpy复制字符串的strlen个字符,当然会失去最后的结束符。

str函数不保证结束符

        这个是比较过分的,str函数不保证结果是合法字符串,strncpy的n小于源字符串长度就不会追加结束符,于是得到了一个非法的字符串,经常会有人忘记了这一点,而这个问题并不总是导致BUG——如果原来的内存后面恰好是NULL,或者后面不长的数据里面就出现了NULL,导致虽然多了一些乱码,程序还是继续运行的。

        微软的描述:

        所以我们习惯上总是在后面手动设置一次结束符:

strncpy(buf,source,n);
buf[n]='\0';

概念完整性

        问题出在哪里呢?问题就出在最初设计C语言的时候偷懒了,字符串不是字符数组,是一种特殊的对象,不应该用字符数组代替字符串。(当然了,我们知道C语言设计之初更多考虑的是性能,用char*表达字符串是一个合理的设计)

        这是设计的一个基本原则:最重要的是概念完整性

        概念准确,没有歧义,不特化,不弱化,这是最高境界。设计失败的系统多多少少都跟概念设计错误有关。错误的概念会诱使程序员和用户犯错。

        高级编程语言没有指针,当然也没有这些混乱。不过话说回来,又是字符串对象、又是字节数组对象,互相转换又麻烦,char *多美妙啊。


(这里是结束)

  • 16
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

初级代码游戏

知识究竟是有价还是无价

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值