• 字符数组和结束符/0之间的关系


    在C中,字符串其实就是字符数组。C语言中,对字符串就是按字符数组的规律来处理的(ANSI的字符是unsigned char,对宽字符,字符是unsigned short int,即前者1byte,后者2byte)。由于是按数组方式处理的,所以必须知道每个串的实际有效元素到哪里结束,想像图书馆书柜中的格子,书柜尽管有100个格子,但未必要放满100本书,可能是10本、20本,所以不能按格数来算字符串长度(算格数那个就是sizeof()的值),实际放书的数量是动态变化的,所以C语言规定某个标志,告诉处理程序,遇到这个标志,就表示书放到此为止,后面不会有书了,这个标志就是'',也是整数0。

    C标准库中的字符串处理程序,是只认''的,只要没找到'',它就认为字符串没有结束,拼命地往后找,这个寻找的过程不理会可能已经超过书柜的格数了(计算机其实很蠢);同样,也可能你在一排书中的中间抽走一本,在那个位置上写上'',那么愚蠢的计算机也会认为书到这里为止,它不理会后面其实还有(这是某种截断字符串的技巧)。

    其实,只要你明白这种类比,自然知道写程序的时候怎么办。比如,当你明白宽字符是16位整数亦即2字符的时候,就会明白,一个宽字符L'A'其实储存有一个字节的0,亦即假如你用常规的ANSI算法来处理这样的字符串,就会很快遇到'',后果如何可想而知。

    标准库函数strlen(),就是在字符数组中搜寻''的简短代码,找到后,把经历过的元素个数返回出来而已。知道这点原理,其实我们并不是必须遵守以''为结束符的cz字符串规则的,以-1结束亦未尝不可,自己写一个_strlen()函数,不用strlen()就可以了。C的灵活性,就体现在这里。须知,C语言本身是没有strlen()这样的内置函数的,它其实就只有那些运算符和数据结构构造规则,你所用的库函数,全部是后人写的代码,不是C语言,最纯正的C语言,应该是所有函数都自己写。标准库函数认cz字符串,你完全可以不认,并非因此而说你没使用C语言写程序。

    像BASIC类的语言,内部其实也是把字符串作数组看待的(所谓C是基础,也是指的这点原理,用来理解别的语言的实现机制,很可能这种语言是用C制作的),只不过,它不用认''作结束符,而把数组的零号元素挪用为字符串长度的记录,所以迫使它的数组计数从1开始,但好处是求数组的有效元素数目不用像C那样遍历数组,而是直接从零号元素读出结果,比遍历快得多——当使用单字节字符系统时,单字节最大值是256,所以很多旧式的语言,字符串最大容量是255或254个字符,就很好理解了。(wsj注:剩余空间用来存放'')

    我们现在再看另一个例子:char* strcat(char* s1, const char* s2)这个函数,是字符串接驳,它的作用是把s2追加在s1的末尾,形成新的字符串。仍然使用上面书柜的例子,既然要在s1的柜子中放入更多的书,那么s1的格子数必须要能容纳全部的书,这是必然的,而书柜是在建造时就造好了的,所以创建s1的时候,首先要考虑这个问题,别指望C库函数会替你想这些,为了高效,它完全不检查这个,闷头就把数据扔过去,它的高效是这样来的(别的语言,为了完成任务,它会智能地做各种动作把任务完成,而C只是做错了报告一声“出错了”就干脆逃跑,被系统杀掉)。在容量满足条件的基础下,函数的动作,首先是找到s1的''位置,然后从s2中逐个把数据复制过来,注意此时必须把''覆盖掉并写上新的'',原因在上面说过了。所以,现在返回头看看函数的原型,它的s1是char*,表明这个字符串是可以被修改的,事实上它必须改这个,而s2是const char*,表明它不需要改动s2,返回的正是s1指针。

    那么,假如要把两个被记录在只读储存空间的字符串接驳成一个,或者已经无法再修改s1的尺寸了,你该怎么做?用strcat是不要指望了,因为此时无法修改s1,你必须自己写一个,用动态申请内存。

    学会语法很简单,但面对具体的情形,如何处理,这才是最需要学习的,假如连这点原理都不知道,那就悲催了,实际上这些动作用不了多复杂的算法、数据结构,但很多人就死在这种地方!现在明白学C到底要学什么了吗?

    实例:

    char s[6]={'h','e','l','l','o'};
    char s[6]={"hello"};
    char s[6]="hello";

    字符数组和字符串的区别:字符数组的每个元素中可存放一个字符,(像这个char s[6]={'h','e','l','l','o'};
    )但他不限定最后一个字符应该是什么,存储空间有剩余系统补‘’。而字符串则要求最后一个必须是‘’做为结束标示。在字符数组中可以存放字符串。
    char s[6]={"hello"};看这个为什么是s[6],而不是s[5]呢?因为,字符串后面以‘’为结束标示,这个是系统补的,不用手动输入。但是必须要给它留一个存储空间。这个‘’它占用存储空间,但是不算字符串长度。

    (wsj注:在申请字符串存储空间时要考虑末尾的结束符''空间,即在单字节字符系统中要多申请一个字节。)

    转自http://bbs.bccn.net/thread-398526-2-1.html

  • 相关阅读:
    6大开源SIEM工具,安全信息和事件管理的“利器”
    数据库为何需要安全审计系统
    WEB漏洞扫描的开源工具
    12种开源Web安全扫描程序
    开源框架openresty+nginx 实现web应用防火墙(WAF)
    锦衣盾:开源WEB应用防火墙介绍
    20步打造最安全的Nginx Web服务器
    MySQL数据库审计系统
    数据库(分库分表)中间件对比
    Mysql调优基础、Mysql问题排查、Mysql优化、与hikari数据库连接池配合
  • 原文地址:https://www.cnblogs.com/liushui-sky/p/5583911.html
Copyright © 2020-2023  润新知