字符串問(wèn)題
字符串
在定義字符串?dāng)?shù)組時(shí)孕荠,C有兩種定義方法:
char* str1 = "0123456789";
char string[10];
在第一種定義中痹升,雖然只有10個(gè)字符叨橱,但是使用了11個(gè)字節(jié)來(lái)保存典蜕。最后一個(gè)字節(jié)為`\0`
當(dāng)進(jìn)行strcpy的時(shí)候,strcpy(string,str1)
這樣就會(huì)導(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 );
}
使用庫(kù)函數(shù)strcpy進(jìn)行拷貝操作愉舔,strcpy會(huì)從原地址一直往后拷貝,直到遇見(jiàn)'\0'為止伙菜。所以拷貝的長(zhǎng)度是不定的轩缤。如果一直沒(méi)有遇到'\0'導(dǎo)致越界訪問(wèn)非法內(nèi)存,程序就崩潰了贩绕。
strcpy
的實(shí)現(xiàn)
如果編寫(xiě)一個(gè)標(biāo)準(zhǔn)strcpy函數(shù)的總分值為10火的,下面給出幾個(gè)不同得分的答案:
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)
{
//對(duì)源地址和目的地址加非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;
}
第五題
檢查下面代碼有什么問(wèn)題
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ù)值。在取得地址后并沒(méi)有返回脱茉,所以str
指針仍然是NULL剪芥。
第六題
下面代碼會(huì)出什么問(wèn)題
char *GetMemory( void )
{
char p[] = "hello world";
return p;
}
void Test( void )
{
char *str = NULL;
str = GetMemory();
printf( str );
}
p[]數(shù)組為函數(shù)內(nèi)的局部自動(dòng)變量,在函數(shù)返回后琴许,內(nèi)存已經(jīng)被釋放税肪。這是許多程序員常犯的錯(cuò)誤,其根源在于不理解變量的生存期榜田。
第七題
下面代碼會(huì)出什么問(wèn)題
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í)行申請(qǐng)內(nèi)存及賦值語(yǔ)句
*p = (char *)malloc(num);
后沒(méi)有判斷內(nèi)存是否申請(qǐng)成功,應(yīng)加上:
if ( *p == NULL )
{
...//進(jìn)行申請(qǐng)內(nèi)存失敗處理
}
未釋放內(nèi)存
printf(str) 改為printf("%s",str),否則可使用格式化字符串攻擊箭券。
第八題
下面代碼會(huì)出什么問(wèn)題
void Test( void )
{
char *str = (char *) malloc( 100 );
strcpy( str, "hello" );
free( str );
... //省略的其它語(yǔ)句
}
沒(méi)有進(jìn)行判斷內(nèi)存是否申請(qǐng)成功净捅;
在free(str)后沒(méi)有把str置為空,可能會(huì)成為一個(gè)野指針辩块。應(yīng)當(dāng)加上str=NULL蛔六;
第九題
下面代碼會(huì)出什么問(wèn)題
swap( int* p1,int* p2 )
{
int *p;
*p = *p1;
*p1 = *p2;
*p2 = *p;
}
需要返回值
p是一個(gè)野指針,有可能指向系統(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++程序国章,請(qǐng)計(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)涵液兽,僅僅只是一個(gè)指針;在失去其內(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í)體的指針凭迹,而且是一個(gè)指針常量罚屋,不能作自增、自減等操作嗅绸,不能被修改脾猛;
char str[10];
str++; //編譯出錯(cuò),提示str不是左值
(3)數(shù)組名作為函數(shù)形參時(shí)鱼鸠,淪為普通指針猛拴。
Windows NT 32位平臺(tái)下羹铅,指針的長(zhǎng)度(占用內(nèi)存的大小)為4字節(jié)愉昆,故sizeof( str ) 职员、sizeof ( p ) 都為4。