C++学习笔记

字符串问题

字符串

在定义字符串数组时,C有两种定义方法:


char* str1 = "0123456789";

char string[10];

在第一种定义中,虽然只有10个字符,但是使用了11个字节来保存。最后一个字节为`\0`

当进行strcpy的时候,strcpy(string,str1) 这样就会导致数组越界。

在进行字符串拷贝时:


void test2()

{

char string[10], str1[10];

int i;

for(i=0; i < 10; i++)

{

str1  = 'a';

}

strcpy( string, str1 );

}

使用库函数strcpy进行拷贝操作,strcpy会从原地址一直往后拷贝,直到遇见'\0'为止。所以拷贝的长度是不定的。如果一直没有遇到'\0'导致越界访问非法内存,程序就崩溃了。


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;

}


第五题

检查下面代码有什么问题


void GetMemory( char *p )

{

p = (char *) malloc( 100 );

}

void Test( void )

{

char *str = NULL;

GetMemory( str );

strcpy( str, "hello world" );

printf( str );

}

GetMemory(char *p)函数中的形参为字符串指针,函数内部修改形参的值并不能真正的改变传入的参数值。在取得地址后并没有返回,所以str指针仍然是NULL。


第六题

下面代码会出什么问题


char *GetMemory( void )

{

char p[] = "hello world";

return p;

}

void Test( void )

{

char *str = NULL;

str = GetMemory();

printf( str );

}

p[]数组为函数内的局部自动变量,在函数返回后,内存已经被释放。这是许多程序员常犯的错误,其根源在于不理解变量的生存期。


第七题

下面代码会出什么问题


void GetMemory( char **p, int num )

{

*p = (char *) malloc( num );

}

void Test( void )

{

char *str = NULL;

GetMemory( &str, 100 );

strcpy( str, "hello" );

printf( str );

}

  1. 传入GetMemory的参数为字符串指针的指针,但是在GetMemory中执行申请内存及赋值语句*p = (char *)malloc(num);后没有判断内存是否申请成功,应加上:

if ( *p == NULL )

{

...//进行申请内存失败处理

}

  1. 未释放内存

  2. printf(str) 改为printf("%s",str),否则可使用格式化字符串攻击。


第八题

下面代码会出什么问题


void Test( void )

{

char *str = (char *) malloc( 100 );

strcpy( str, "hello" );

free( str );

... //省略的其它语句

}

没有进行判断内存是否申请成功;

在free(str)后没有把str置为空,可能会成为一个野指针。应当加上str=NULL;


第九题

下面代码会出什么问题


swap( int* p1,int* p2 )

{

int *p;

*p = *p1;

*p1 = *p2;

*p2 = *p;

}

需要返回值

p是一个野指针,有可能指向系统区,应该改为:


void swap( int* p1,int* p2 )

{

int p;

p = *p1;

*p1 = *p2;

*p2 = p;

}


如何判断flot类型变量是否为零

const float EPSINON = 0.00001;

if(x >= -EPSINON && x<= EPSINON)


第11题

以下为Windows NT下的32位C++程序,请计算sizeof的值


void Func ( char str[100] )

{

sizeof( str ) = ?

}

void *p = malloc( 100 );

sizeof ( p ) = ?

sizeof( str ) = 4

sizeof ( p ) = 4

【剖析】

Func ( char str[100] )函数中数组名作为函数形参时,在函数体内,数组名失去了本身的内涵,仅仅只是一个指针;在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。

数组名的本质如下:

(1)数组名指代一种数据结构,这种数据结构就是数组;

例如:


char str[10];

cout << sizeof(str) << endl;

输出结果为10,str指代数据结构char[10]。

(2)数组名可以转换为指向其指代实体的指针,而且是一个指针常量,不能作自增、自减等操作,不能被修改;

char str[10];

str++; //编译出错,提示str不是左值

(3)数组名作为函数形参时,沦为普通指针。

Windows NT 32位平台下,指针的长度(占用内存的大小)为4字节,故sizeof( str ) 、sizeof ( p ) 都为4。

你可能感兴趣的:(C++学习笔记)