C语言&嵌入式

C语言面试题---字符串拷贝函数与内存拷贝函数

2017-12-28  本文已影响67人  安想创新教育

版权声明:本文转载于公众号TeachPlus---C语言面试题---字符串拷贝函数与内存拷贝函数


                

看看下面的这题:

strcpy()和memcpy()的区别?

答案:

strcpy是字符串拷贝函数

memspy是内存拷贝函数

strcpy()和memcpy()都可以用来拷贝字符串,strcpy()拷贝以’\0’结束,

但memcpy()必须指定拷贝的长度。

本题解析

本题的重点一个是这两个函数的使用,另一个就是关于字符串的结束标志'\0'了。

c语言中的字符串,实际上就是一个字符数组,那么怎么把字符串字符数组区分开来,就得用到字符串的结束标志了。

对于上面的两个问题,大家可以下面的程序作为参考:

# include  <stdio.h>

# include  <stdlib.h>

# include  <string.h>

int main()

{

    charstr1[20] ="hello world";

    charstr2[20];

    charstr3[20];

    memset(str2,2,20);

    memset(str3,2,20);

    strcpy(str2,str1);

    memcpy(str3,str1,5);

    printf("%s\n",str2);

    printf("%s\n",str3);

    return0;

}

程序输出为:

该程序首先声明了三个字符数组,并且将str1初始化为"hello world";

然后使用memset函数,将str2和str3数组中的内容全部置为2,

以确保内存中没有原来就存在的'\0';

接下来使用strcpy方法将str1 中的内容拷贝到str2中

再将str3使用memcpy直接进行内存拷贝,拷贝五个字节到str3中。

最终输出str2和str3的内容。

从输出的结果大家可以看到,str2的输出是正常的。

因为strcpy在进行拷贝时,自动的将字符串的结束表示进行了拷贝,

printf函数在输出的过程中检测到了'\0'标志则停止输出。

而对于str3则输出了一大串乱码。这是因为 memcpy函数在进行拷贝的时候,

只进行了制定的字节数的内存的拷贝,并没有自动添加'\0'标志,

因此在printf函数输出时,不能够发现结束标志,

所以一直将后面的乱码输出了出来,后面的乱码就是我们在一开始的时

候通过memset函数设置的2了。

相关知识点

针对于字符串类的操作函数,可以考察的方面有很多种,大家可以参考下面的几道面试题:

问:请找出下面代码里的问题:

#include  <stdio.h>

intmain(void)

{

    charbuff[10];

    memset(buff,0,sizeof(buff));

    gets(buff);

    printf("\n The buffer entered is [%s]\n",buff);

    return0;

}

答:上面代码里的问题在于函数gets()的使用,这个函数从stdin接收一个字符串而不检查它所复

制的缓存的容积,这可能会导致缓存溢出。这里推荐使用标准函数fgets()代替。

还有一道题目非常有意思,单看题目来说,可能会被唬住

问:下面是一个简单的密码保护功能,你能在不知道密码的情况下将其破解吗?

# include   <stdio.h>

int main(intargc,char*argv[])

{

    intflag = 0;

    charpasswd[10];

    memset(passwd,0,sizeof(passwd));

    strcpy(passwd, argv[1]);

    if(0 == strcmp("LinuxGeek", passwd))

    {

        flag = 1;

    }

    if(flag)

    {

        printf("\n Password cracked \n");

    }

    else

    {

        printf("\n Incorrect passwd \n");

    }

    return0;

}

答:破解上述加密的关键在于利用攻破strcpy()函数的漏洞。所以用户在向“passwd”缓存输入随

机密码的时候并没有提前检查“passwd”的容量是否足够。所以,如果用户输入一个足够造成缓

存溢出并且重写“flag”变量默认值所存在位置的内存的长“密码”,即使这个密码无法通过验证,

flag验证位也变成了非零,也就可以获得被保护的数据了。例如:

$ ./psswd aaaaaaaaaaaaa

Password cracked

虽然上面的密码并不正确,但我们仍然可以通过缓存溢出绕开密码安全保护。

要避免这样的问题,建议使用 strncpy()函数。

对于字符串来说,比较重要的知识点,第一个时结尾标志'\0'的使用,第二个就是各种操作函数了

对于操作函数来说,可能绝大部分人接触的都是下面这种函数:

总结

gets

//没有边界检查,容易造成溢出

scanf

//不能接收带有空格的字符串

strcpy

//没有边界检查,容易造成溢出

strcmp

//没有边界检查,容易造成溢出

strcat

//没有边界检查,容易造成溢出

但是以上函数都有各自的缺点,因此推荐使用以下函数进行替代:

fgets

strncpy

strncmp

strncat

另外,最好时能够自己实现一下这些函数,这也是面试中常常会考察的一部分

上一篇下一篇

猜你喜欢

热点阅读