一道面试题目
找出下边代码中的错误:
void test1()
{
char string[10];
char* str1 = "0123456789";
strcpy( string, str1 );
}
大家看看有哪些错误?
[解决办法]
越界
[解决办法]
用strcpy()会出现数组越界!
用
cout < <a[0] < <endl;
cout < <a[9] < <endl;
每次只输出单个char的值,是可正常执行的。
[解决办法]
因为这不是JAVA
[解决办法]
拷贝过程是没有问题的。
数组里面就是那十个数。
你可以查看以下memory
退出的时候才会crash的。
[解决办法]
从理论上说
strcpy( string, str1 );
这条语句会报错,因为
char* str1 = "0123456789";
str实际指向的是11个字符的空间地址,字符串的结束符‘\0’也占一个字节。
而执行strcpy函数把一个11个字节长的字符串赋给10字节长的数组是显然越界了的。
但在32位机上安装的VC++6.0上调试该函数,并不会报错,楼主可以自己动手试试!
[解决办法]
- C/C++ code
char string[10], str1[10]; int i; for(i=0; i <10; i++) { str1[color=#FF6600][i] [/color]= 'a'; } strcpy( string, str1 );
[解决办法]
str1是11个字符,最后一个是字符串的结束符‘\0’(为了兼容c语言),而sting[10]只是10,所以会出现数组越界。
[解决办法]
12楼的说的太对了,strcpy函数是用于以结束符\0'字符串的拷贝,对于没有结束符'\0'的字符串,虽然在有的编译器上能编译,但它是不合法的,当然是不是越界我不太清楚,不过我记得好象对于不同的字符串好象也能拷贝,只是有数据的 损失!
[解决办法]
- C/C++ code
void test1() { char string[10]; char* str1 = "0123456789"; strcpy( string, str1 ); }
[解决办法]
这个问题初学者经常会很疑惑。我简单的解释一下~
void test1()
{
char string[10];
char* str1 = "0123456789";
strcpy( string, str1 );
}
上面这个strcpy确实越界了,破坏的是堆栈的数据。但是这个越界造成的影响不一定就会导致程序异常。注意,这里说的是不一定会,不是一定不会。
首先要了解一个事实:调用test1函数的时候,会将调用点的下一条语句的地址记录在堆栈中。然后这个函数执行完了,把开始记录的地址取出来,继续运行。也就是说,只要堆栈里的返回地址不被修改,那么继续正常运行下去是没问题的。
在VC6环境下,DEBUG版本因为要支持Edit and Continue的特性,为每个函数在堆栈中多分配了64个字节的多余数据。也就是说,只要越界的不是足够多的话,或者说没有修改函数返回地址,是不会发生异常的。Release环境下就没有这64个字节了,但是LZ的这个代码仍然不会出错。因为char string[10]要求堆栈分配10个字节。但是堆栈分配的时候是4字节对其,所以实际上分配了12个字节。也就是说这里多写的1个字节还是没影响函数返回地址。
lz不妨把str1定义为一个超过11字节的数据看看是不是出错。。。 不过,不出错的概率不是100%的。
[解决办法]
自己发的文章,自己不能修改吗?
刚才写了个函数看了一下,上面说错一个地方。DEBUG版本多分配的64字节是在函数局部变量的前面,不是导致Debug版没有出错的原因。应该是跟Release版的解释相同。
[解决办法]
越界。
使用strcpy(a, b), 一定要检查a, b是否满足条件:a的长度 > b的长度。这里说的长度是字符串到'\0'结束的长度。
"0123456789"的实际长度为11(包括最后的'\0').
string[10]只有10,使用strcpy越界。
[解决办法]
给楼主看一些东西
试题1:
void test1()
{
char string[10];
char* str1 = "0123456789";
strcpy( string, str1 );
}
试题2:
void test2()
{
char string[10], str1[10];
int i;
for(i=0; i<10; i++)
{
str1 = 'a';
}
strcpy( string, str1 );
}
试题3:
void test3(char* str1)
{
char string[10];
if( strlen( str1 ) <= 10 )
{
strcpy( string, str1 );
}
}
解答:
试题1字符串str1需要11个字节才能存放下(包括末尾的’\0’),而string只有10个字节的空间,strcpy会导致数组越界;
对试题2,如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string, str1)调用使得从str1[url=]内存[/url]起复制到string内存起所复制的字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10分;
对试题3,if(strlen(str1) <= 10)应改为if(strlen(str1) < 10),因为strlen的结果未统计’\0’所占用的1个字节。
剖析:
考查对基本功的掌握:
(1)字符串以’\0’结尾;
(2)对数组越界把握的敏感度;
(3)库函数strcpy的工作方式,如果编写一个标准strcpy函数的总分值为10,下面给出几个不同得分的答案:
2分
void strcpy( char *strDest, char *strSrc )
{
while( (*strDest++ = * strSrc++) != ‘\0’ );
}
4分
void strcpy( char *strDest, const char *strSrc )
//将源字符串加const,表明其为输入参数,加2分
{
while( (*strDest++ = * strSrc++) != ‘\0’ );
}
7分
void strcpy(char *strDest, const char *strSrc)
{
//对源地址和目的地址加非0断言,加3分
assert( (strDest != NULL) && (strSrc != NULL) );
while( (*strDest++ = * strSrc++) != ‘\0’ );
}
10分
//为了实现链式操作,将目的地址返回,加3分!
char * strcpy( char *strDest, const char *strSrc )
{
assert( (strDest != NULL) && (strSrc != NULL) );
char *address = strDest;
while( (*strDest++ = * strSrc++) != ‘\0’ );
return address;
}
从2分到10分的几个答案我们可以清楚的看到,小小的strcpy竟然暗藏着这么多玄机,真不是盖的!需要多么扎实的基本功才能写一个完美的strcpy啊!
[解决办法]
越界
[解决办法]
好简单,因为'\0'没得放
[解决办法]
1.数组越界问题
2.const char*指向的空间内容不可修改
如:
- C/C++ code
char* p="csdn";//或const char* p="csdn";*p='c';//Error! *p为const char型别
[解决办法]
[Quote=引用:]
- C/C++ code
试题1: void test1() { char string[10]; char* str1 = "0123456789"; strcpy( string, str1 ); } 试题2: void test2() { char string[10], str1[10]; int i; for(i=0; i <10; i++) { str1 = 'a'; } strcpy( string, str1 ); } 试题3: void test3(char* str1) { char string[10]; if( strlen( str1 ) <= 10 ) { strcpy( string, str1 ); } }
[解决办法]
//为了实现链式操作,将目的地址返回,加3分!
- C/C++ code
char * strcpy( char *strDest, const char *strSrc ) { // assert( (strDest != NULL) && (strSrc != NULL) ); assert( (strDest != NULL) && (strSrc != NULL) && (strDest != strSrc) ); char *address = strDest; while( (*strDest++ = * strSrc++) != ‘\0’ ); return address; }
[解决办法]
貌似数组在声明时还要赋初值吧,也就是直接定义拉
[解决办法]
字符指针本质上是个字符串,所以可以将此字符串赋值进数组。