为了账号安全,请及时绑定邮箱和手机立即绑定

合并函数strcat()运用时字符串数组中为0的元素难道被舍去?

合并函数strcat()运用时字符串数组中为0的元素难道被舍去?

C
慕斯卡9202087 2016-08-24 21:48:36
#include <stdio.h>int main(){    char s1[20] = "Hello";    char s2[6] = "World";    strcat (s1,s2);    puts(s1);}难道定义数组s1不会有0在后面,s2也有0啊(难道大写占两个字符?就算是两个s1后面也要跟很多0啊)定义数组不是多余的元素被赋予0吗?难道字符串数组不是这样的?
查看完整描述

4 回答

?
onemoo

TA贡献883条经验 获得超454个赞

s1后面是有0:

你说得没错,s1就是char数组,定义时未初始化的部分为0,并且字符串后面会加上一个'\0'代表字符串结尾。所以s1的开头的5个元素是'H' 'e' 'l' 'l' 'o',后面一个'\0',剩下的都是0。

s2也是同样的道理,当然s2的大小正好容纳下W o r l d这5个字符和一个'\0',所以后面没有多余的0了。


你想问的是不是:为什么strcat函数就知道要把s2中的字符串接在s1中最后一个字符'o'后面?

C语言规定字符串的形式就是:内存中的连续存放的一串char,并且用'\0'代表字符串的结束

所以strcat函数——包括库中所有处理字符串的函数——都是这样判断的:strcat从s1中读到第一个'\0',它就知道这串字符串到这里就结束了,然后会把s2中的字符依次拷贝到s1中的这个'\0'及后面的内存中,直到拷贝到s2中的'\0',函数就知道s2所表示的字符串也结束了,最后它会保证这个新连接成的字符串也是以'\0'做结尾的(必须以'\0'标志字符串结束)。


这样看,你也可以说是s1中后面的0被舍去了。 那些0虽然在s1数组中,但它们根本就不算是字符串的一部分。库中的字符串处理函数永远是用'\0'来判断字符串是否到结尾的。


而且从strcat函数工作流程的描述中你也能看出来:函数只是在不断将字符拷贝过来,直到'\0'才结束拷贝,函数根本不管到底要拷贝多少个! 这才是为什么要求s1有足够大的大小来容纳连接后的字符串,并且这一点需要由程序员来保证!

查看完整回答
2 反对 回复 2016-08-24
  • 慕斯卡9202087
    慕斯卡9202087
    仔细看完了答主的回答,思索了许久提出下面没想清的问题。C语言字符串的定义是连续存放的一串char,并且以\0代表字符串的结束,外加答主肯定了我问的s1数组有许多的0,那么strcat函数拼接的时候为什么不是把Hello00000000000000World呢?答主告诉我0被舍去,想知道原理,另外一个问题,s1有足够的大小来容纳连接后的字符串是不是在此题中s1最小需要10+1个数组元素定义的大小?很感激答主的帮忙!
?
wwpbjing

TA贡献20条经验 获得超5个赞


不好意思,这几天加班,这会儿才得空,回答下你的问题:
第一个问题:
我尽量不敷衍地告诉你记住就可以了,而会尝试从原理讲明白为什么初始化成'\0'而不是'0'
首先你得先了解一个叫ASSCII(美国信息交换标准代码)的东西,详细定义可以看下wiki或者百度百科:
引用百度百科图片:
//img1.sycdn.imooc.com/57bfe67e00010f7e12730894.jpg

在C语言中char类型占1byte,即8bit,能够表示的范围是00000000~11111111(二进制),即0~255(十进制),实际存储的就是ASCII码
比如'0'在上图表示48(十进制)即00110000(二进制)
再比如'\0'在上图表示0(十进制)即00000000(二进制)
发现了吗?char类型的0实际上是00000000即我们平常所说的'\0',显然即便是你设计也不会设计成默认补00110000('0')吧?
这下你理解了吧?至于为什么初始化为'\0',这个大概是编译器编译、链接、生成可执行代码后,由计算机执行时会自动为没有赋值的字符补'\0'吧,至于更加深入的比如机器执行二进制代码和编译器gcc的编译过程就没有研究过了。
第二个问题:
是的,不好意思笔误指向\0
第三个问题:
*在C语言中是指针,是C/C++语言的特色也是难点,简单说就是个8bit数字(64位机器),表示内存地址,

char s1[20]="Hello";
char *dest = s1;
char *tmp = dest;
// 上一行代码含义
// s1:
// Hello\0\0\0\0\0...\0
// ^
// |
// *tmp,*dest

上面这段注释表示char类型的指针tmp和char类型的指针dest都指向字符数组s1的首地址,有关指针的详细的教程你只要继续深入地往下学,就都会明白了,要想完全理解函数strcat的源码,需要你理解指针,我只是简单告诉你含义

查看完整回答
1 反对 回复 2016-08-26
?
onemoo

TA贡献883条经验 获得超454个赞

写不开,我再开一贴:

我的回答中其实已经讲解了为什么那些0不会保留下来。并且我并没有直接告诉你“0被舍去”。

我先告诉了你C语言中字符串的形式——就是以'\0'结尾的一串char。 

然后我向你描述了strcat的工作原理——strcat的作用是拼接字符串,所以它就把s1作为字符串来看待。字符串就是内存中的连续存放的一串char,并且用'\0'代表字符串的结束

strcat看到s1中开头依次是H e l l o后,发现后面是一个'\0',于是它就知道这字符串结束了,随后它会将s2处的字符拼接到刚刚的那个'\0'那里(会覆盖掉这个'\0')...  我前面和你说“你也可以把这行为看作是0被舍去”,但实际上strcat根本就不会在数组20个元素之后再拼接,相反它是从s1所代表的字符串结束处——也就是Hello后面的第一个'\0'处——开始拼接s2所代表字符串。  

另外,虽然你没问,不管s2有多大——就算s2是有100个char的数组(s2中剩下的部分也都是0)——strcat也并不会将s2数组的全部内容都拼接过来。 原因是同样的:strcat把s2也看作是字符串,它发现World后面的'\0'时就知道s2所代表的字符串结束了,不会再继续拷贝后面的内容了。

总之,strcat并没有把s1当作含有20个char的数组来看待(事实上strcat根本就不知道s1是个数组),strcat完全是把它当作依据字符串来看待的。


最后你问的s1的大小是否至少要有10+1个?   

没错是这样的,s1至少要能存储HelloWorld这10个字符和最后的1个'\0'。

查看完整回答
1 反对 回复 2016-08-25
  • 4 回答
  • 0 关注
  • 3021 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信