字符串問題
字符串
在定義字符串?dāng)?shù)組時(shí),C有兩種定義方法:
char* str1 = "0123456789";
char string[10];
在第一種定義中,雖然只有10個字符,但是使用了11個字節(jié)來保存。最后一個字節(jié)為`\0`
當(dāng)進(jìn)行strcpy的時(shí)候,strcpy(string,str1) 這樣就會導(dǎo)致數(shù)組越界。
在進(jìn)行字符串拷貝時(shí):
void test2()
{
char string[10], str1[10];
int i;
for(i=0; i < 10; i++)
{
str1 = 'a';
}
strcpy( string, str1 );
}
使用庫函數(shù)strcpy進(jìn)行拷貝操作,strcpy會從原地址一直往后拷貝,直到遇見'\0'為止。所以拷貝的長度是不定的。如果一直沒有遇到'\0'導(dǎo)致越界訪問非法內(nèi)存,程序就崩潰了。
strcpy的實(shí)現(xiàn)
如果編寫一個標(biāo)準(zhǔn)strcpy函數(shù)的總分值為10,下面給出幾個不同得分的答案:
2分
void strcpy( char *strDest, char *strSrc )
{
while( (*strDest++ = * strSrc++) != ‘\0’ );
}
4分
void strcpy( char *strDest, const char *strSrc )
//將源字符串加const,表明其為輸入?yún)?shù),加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分
//為了實(shí)現(xiàn)鏈?zhǔn)讲僮?,將目的地址返回,?分!
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)函數(shù)中的形參為字符串指針,函數(shù)內(nèi)部修改形參的值并不能真正的改變傳入的參數(shù)值。在取得地址后并沒有返回,所以str指針仍然是NULL。
第六題
下面代碼會出什么問題
char *GetMemory( void )
{
char p[] = "hello world";
return p;
}
void Test( void )
{
char *str = NULL;
str = GetMemory();
printf( str );
}
p[]數(shù)組為函數(shù)內(nèi)的局部自動變量,在函數(shù)返回后,內(nèi)存已經(jīng)被釋放。這是許多程序員常犯的錯誤,其根源在于不理解變量的生存期。
第七題
下面代碼會出什么問題
void GetMemory( char **p, int num )
{
*p = (char *) malloc( num );
}
void Test( void )
{
char *str = NULL;
GetMemory( &str, 100 );
strcpy( str, "hello" );
printf( str );
}
- 傳入GetMemory的參數(shù)為字符串指針的指針,但是在GetMemory中執(zhí)行申請內(nèi)存及賦值語句
*p = (char *)malloc(num);后沒有判斷內(nèi)存是否申請成功,應(yīng)加上:
if ( *p == NULL )
{
...//進(jìn)行申請內(nèi)存失敗處理
}
未釋放內(nèi)存
printf(str) 改為printf("%s",str),否則可使用格式化字符串攻擊。
第八題
下面代碼會出什么問題
void Test( void )
{
char *str = (char *) malloc( 100 );
strcpy( str, "hello" );
free( str );
... //省略的其它語句
}
沒有進(jìn)行判斷內(nèi)存是否申請成功;
在free(str)后沒有把str置為空,可能會成為一個野指針。應(yīng)當(dāng)加上str=NULL;
第九題
下面代碼會出什么問題
swap( int* p1,int* p2 )
{
int *p;
*p = *p1;
*p1 = *p2;
*p2 = *p;
}
需要返回值
p是一個野指針,有可能指向系統(tǒng)區(qū),應(yīng)該改為:
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++程序,請計(jì)算sizeof的值
void Func ( char str[100] )
{
sizeof( str ) = ?
}
void *p = malloc( 100 );
sizeof ( p ) = ?
sizeof( str ) = 4
sizeof ( p ) = 4
【剖析】
Func ( char str[100] )函數(shù)中數(shù)組名作為函數(shù)形參時(shí),在函數(shù)體內(nèi),數(shù)組名失去了本身的內(nèi)涵,僅僅只是一個指針;在失去其內(nèi)涵的同時(shí),它還失去了其常量特性,可以作自增、自減等操作,可以被修改。
數(shù)組名的本質(zhì)如下:
(1)數(shù)組名指代一種數(shù)據(jù)結(jié)構(gòu),這種數(shù)據(jù)結(jié)構(gòu)就是數(shù)組;
例如:
char str[10];
cout << sizeof(str) << endl;
輸出結(jié)果為10,str指代數(shù)據(jù)結(jié)構(gòu)char[10]。
(2)數(shù)組名可以轉(zhuǎn)換為指向其指代實(shí)體的指針,而且是一個指針常量,不能作自增、自減等操作,不能被修改;
char str[10];
str++; //編譯出錯,提示str不是左值
(3)數(shù)組名作為函數(shù)形參時(shí),淪為普通指針。
Windows NT 32位平臺下,指針的長度(占用內(nèi)存的大?。?字節(jié),故sizeof( str ) 、sizeof ( p ) 都為4。