经典C语言能力测试题(值得一看)
生活随笔
收集整理的這篇文章主要介紹了
经典C语言能力测试题(值得一看)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
絕對能夠測試你的C語言功力的幾個問題!
很少有真正精通了C語言編程的學員,一般都有或多或少概念不是完全清楚的問題,特別是一些需要豐富的實戰經驗才能體會和明白的問題,如字符串,指針,類型轉換,定義指向函數的指針類型,這也是導致學習C困難的一個原因。下面有幾個簡單測試將能發現你對C語言的掌握情況。
1)int x=35;
char str[10];
//問:strlen(str)和sizeof(str)的值分別是多少?
答:strlen(str) 值不確定,strlen根據'/0'確定字符串是否結束。
sizeof(str)=10 sizeof一個數組為數組長度
strcpy(str,"www.it315.org"/*共13個字母*/);
//問:此時x和strlen(str)的值分別是多少?
答:x 為35
strcpy(char* dest, const char* src)
根據src來復制dest,依照src的'/0'決定復制的長度,而dest必須要提供足夠的長度,這里會引起溢出,strlen返回13,但是數組外部的數據已經被破壞
strlen的值為13,在VC++環境下,x的值是要改變的(其他編譯器下沒試,).雖然表面上看來,在程序中并沒有修改x的值,但是實際運行的結果是上面的x的值發生了修改,這是因為strcpy以后,把多余的數據拷貝進了str的鄰居(int類型的x)中,所以x的數據也就變了.這是一個曾讓我刻骨銘心的問題,在我剛出道時遇到這個問題,雖然在朋友的幫助下解決了這個問題,但一直不明白x的值為何變了,只有最后走上培訓教師的崗位,才開始梳理自己曾經的困惑,才開始總結以前的經驗供學員們借鑒.我覺得這個題目的價值非常之大,它能引起學員對字符串拷貝越界問題的足夠重視,并且通過這個問題更能明白字符串的處理是怎么回時,更能明白字符串與字符數組的關系:字符串就是一個字符數組,只是把這個字符數組用在處理串的函數中時,這些函數不考慮數組的長度,只是記住數組的首地址,從首地址開始處理,并在遇到0時結束處理,
3)char str[10];
str="it315.org";
//編譯能通過嗎?
答:數組不能賦值,只能初始化。char str[10] = "it315.org";
而且初始化時編譯器會檢查數組的長度與初始化串的長度是否匹配
4)char *pstr;
strcpy(pstr,"http://www.it315.org");
//上句編譯能通過嗎?運行時有問題嗎?
答:可以通過編譯,但是pstr指向了常量區,運行時最好只做讀操作,寫操作不保險。
編譯可以通過,但是pstr沒有進行有效的初始化,它指向了一個不確定的內存區,運行時會出現內存不可寫錯誤!
const char *p1;
char * const p2;
//上面兩句有什么區別嗎?
答:const char* 和 char const* 一樣,都是表示指向常量的字符指針。
char * const 表示指向字符的常量指針
p1=(const char *)str;
//如果是p1=str;編譯能夠通過嗎?明白為什么要類型轉換?類型轉換的本質是什么?
答:可以通過編譯。關于常量與非常量指針的關系是這樣的:
const指針可以指向const或者非const區域,不會造成什么問題。
非const指針不能指向const區域,會引起錯誤。(呵呵,這個問題,很經典)
strcpy(p1,"abc");//編譯能夠通過嗎?
答:不能通過,strcpy( char*, const char*); char* 不能指向const char*
注意:非const指針不能指向const區域,會引起錯誤。
printf("%d",str);//有問題嗎?
答:沒有問題,輸出的是str的地址信息
pstr=3000;//編譯能過嗎?如果不行,該如何修改以保證編譯通過呢?
答:不能通過,char* pstr表示pstr是個字符指針,不能指向3000的整形變量。
修改的話,可以這樣:pstr = (char*)3000,把pstr指向3000這個地址;
long y=(long)pstr;//可以這樣做嗎?
答:可以,y的值為pstr所指的地址。不過如果是純粹要地址的話,最好是用unsigned long。
int *p=str;
*p=0x00313200;
printf("%s",str);//會是什么效果?提示0x31對應字符'1',0x32對應字符'2'。
答:首先編譯未必會過關,有些編譯器可能不允許int * 直接指向char*。最好是改為int *p = (int*)str;
過關了效果就是什么東西都沒有。int *p=str; p為str所指的地址,*p表示修改了str所指向的內存。
由于sizeof(int)在32位機上,int有4個字節(其實具體要看編譯器的配置文件,好像是limit.h,一般是4個字節)所以修改了str[0]-str[3]
由于0x00313200頭尾都是0,所以字符串為'/0'開頭,什么都打印不出來。這里有個Big-endin和little-endin的問題。以0x31323334為例
little-endin的機器上面,0x31323334在內存中排列順序為34 33 32 31,輸出為4321,如INTEL芯片的pc
big-endin機器上面為31 32 33 34 ,輸出為1234,如IBM POWERPC
p=3000;//p+1的結果會是多少?
答:3000+sizeof(int); 指針+1均為原來地址加上sizeof(指針所指的數據類型)
char *pc=new char[100];//上述語句在內存中占據幾個內存塊,怎樣的布局情況?
答: 本身pc會占用函數棧一個4字節的指針長度(具體是否為4個字節要看機器和編譯器)。
new會在堆上申請100個字節sizeof(char)的連續空間。
void test(char **p)
{
*p=new char[100];
}//這個編譯函數有問題嗎?外面要調用這個函數,該怎樣傳遞參數?
答:該程序沒有問題。需要在函數中對指針所指的地址進行變化是必須傳入指針的地址。
原因是這樣的:如果傳入的為指針本身,在函數調用的時候,實參會被復制一個實例,這 樣就不是原來的指針了,對該指針本身進行的任何改變都不能傳遞回去了。
可以這樣理解,如果傳入的參數為int,那么對int本身的值的改變就傳不回去啦,加個*也是一樣的。
//能明白typedef int (*PFUN)(int x,int y)及其作用嗎?
答:定義了一個函數指針類型的宏,這樣PFUN就表示指向返回值為int,且同時帶2個int 參數的函數指針類型了。
可以用來定義這樣的變量:
比如有個函數為int fun( int x, int y );
PFUN p = fun;
補充::函數指針最大的用處在于它可以被一個模板方法調用,這是我在學java的設計模式時領悟到的.例如,有兩個函數的流程結構完全一致,只是內部調用的具體函數不同,如下所示:
void func1()
{
//一段流程代碼和面向方面的代理,如安全檢查,日志記錄等
int sum = add( x , y);
//一段流程代碼和面向方面的代理,如安全檢查,日志記錄等
}
void func2()
{
//與func1完全相同的一段流程代碼和面向方面的代理,如安全檢查,日志記錄等
int difference = sub( x , y);
//與func1完全相同的一段流程代碼和面向方面的代理,如安全檢查,日志記錄等
}
那么,可以只定義一個函數,如下所示
void func(PFUNC p)
{
//與func1完全相同的一段流程代碼和面向方面的代理,如安全檢查,日志記錄等
int difference = p( x , y);
//與func1完全相同的一段流程代碼和面向方面的代理,如安全檢查,日志記錄等
}
調用程序在調用時,讓參數p分別指向add和sub函數就可以了.
對于許多類似的問題一般從書本上是看不到的,不通過大量的實踐與調試是難以理解和令人困惑的,所以在本文中對于類似上述的C語言問題都將作出詳細的解釋和講解。
很少有真正精通了C語言編程的學員,一般都有或多或少概念不是完全清楚的問題,特別是一些需要豐富的實戰經驗才能體會和明白的問題,如字符串,指針,類型轉換,定義指向函數的指針類型,這也是導致學習C困難的一個原因。下面有幾個簡單測試將能發現你對C語言的掌握情況。
1)int x=35;
char str[10];
//問:strlen(str)和sizeof(str)的值分別是多少?
答:strlen(str) 值不確定,strlen根據'/0'確定字符串是否結束。
sizeof(str)=10 sizeof一個數組為數組長度
strcpy(str,"www.it315.org"/*共13個字母*/);
//問:此時x和strlen(str)的值分別是多少?
答:x 為35
strcpy(char* dest, const char* src)
根據src來復制dest,依照src的'/0'決定復制的長度,而dest必須要提供足夠的長度,這里會引起溢出,strlen返回13,但是數組外部的數據已經被破壞
strlen的值為13,在VC++環境下,x的值是要改變的(其他編譯器下沒試,).雖然表面上看來,在程序中并沒有修改x的值,但是實際運行的結果是上面的x的值發生了修改,這是因為strcpy以后,把多余的數據拷貝進了str的鄰居(int類型的x)中,所以x的數據也就變了.這是一個曾讓我刻骨銘心的問題,在我剛出道時遇到這個問題,雖然在朋友的幫助下解決了這個問題,但一直不明白x的值為何變了,只有最后走上培訓教師的崗位,才開始梳理自己曾經的困惑,才開始總結以前的經驗供學員們借鑒.我覺得這個題目的價值非常之大,它能引起學員對字符串拷貝越界問題的足夠重視,并且通過這個問題更能明白字符串的處理是怎么回時,更能明白字符串與字符數組的關系:字符串就是一個字符數組,只是把這個字符數組用在處理串的函數中時,這些函數不考慮數組的長度,只是記住數組的首地址,從首地址開始處理,并在遇到0時結束處理,
3)char str[10];
str="it315.org";
//編譯能通過嗎?
答:數組不能賦值,只能初始化。char str[10] = "it315.org";
而且初始化時編譯器會檢查數組的長度與初始化串的長度是否匹配
4)char *pstr;
strcpy(pstr,"http://www.it315.org");
//上句編譯能通過嗎?運行時有問題嗎?
答:可以通過編譯,但是pstr指向了常量區,運行時最好只做讀操作,寫操作不保險。
編譯可以通過,但是pstr沒有進行有效的初始化,它指向了一個不確定的內存區,運行時會出現內存不可寫錯誤!
const char *p1;
char * const p2;
//上面兩句有什么區別嗎?
答:const char* 和 char const* 一樣,都是表示指向常量的字符指針。
char * const 表示指向字符的常量指針
p1=(const char *)str;
//如果是p1=str;編譯能夠通過嗎?明白為什么要類型轉換?類型轉換的本質是什么?
答:可以通過編譯。關于常量與非常量指針的關系是這樣的:
const指針可以指向const或者非const區域,不會造成什么問題。
非const指針不能指向const區域,會引起錯誤。(呵呵,這個問題,很經典)
strcpy(p1,"abc");//編譯能夠通過嗎?
答:不能通過,strcpy( char*, const char*); char* 不能指向const char*
注意:非const指針不能指向const區域,會引起錯誤。
printf("%d",str);//有問題嗎?
答:沒有問題,輸出的是str的地址信息
pstr=3000;//編譯能過嗎?如果不行,該如何修改以保證編譯通過呢?
答:不能通過,char* pstr表示pstr是個字符指針,不能指向3000的整形變量。
修改的話,可以這樣:pstr = (char*)3000,把pstr指向3000這個地址;
long y=(long)pstr;//可以這樣做嗎?
答:可以,y的值為pstr所指的地址。不過如果是純粹要地址的話,最好是用unsigned long。
int *p=str;
*p=0x00313200;
printf("%s",str);//會是什么效果?提示0x31對應字符'1',0x32對應字符'2'。
答:首先編譯未必會過關,有些編譯器可能不允許int * 直接指向char*。最好是改為int *p = (int*)str;
過關了效果就是什么東西都沒有。int *p=str; p為str所指的地址,*p表示修改了str所指向的內存。
由于sizeof(int)在32位機上,int有4個字節(其實具體要看編譯器的配置文件,好像是limit.h,一般是4個字節)所以修改了str[0]-str[3]
由于0x00313200頭尾都是0,所以字符串為'/0'開頭,什么都打印不出來。這里有個Big-endin和little-endin的問題。以0x31323334為例
little-endin的機器上面,0x31323334在內存中排列順序為34 33 32 31,輸出為4321,如INTEL芯片的pc
big-endin機器上面為31 32 33 34 ,輸出為1234,如IBM POWERPC
p=3000;//p+1的結果會是多少?
答:3000+sizeof(int); 指針+1均為原來地址加上sizeof(指針所指的數據類型)
char *pc=new char[100];//上述語句在內存中占據幾個內存塊,怎樣的布局情況?
答: 本身pc會占用函數棧一個4字節的指針長度(具體是否為4個字節要看機器和編譯器)。
new會在堆上申請100個字節sizeof(char)的連續空間。
void test(char **p)
{
*p=new char[100];
}//這個編譯函數有問題嗎?外面要調用這個函數,該怎樣傳遞參數?
答:該程序沒有問題。需要在函數中對指針所指的地址進行變化是必須傳入指針的地址。
原因是這樣的:如果傳入的為指針本身,在函數調用的時候,實參會被復制一個實例,這 樣就不是原來的指針了,對該指針本身進行的任何改變都不能傳遞回去了。
可以這樣理解,如果傳入的參數為int,那么對int本身的值的改變就傳不回去啦,加個*也是一樣的。
//能明白typedef int (*PFUN)(int x,int y)及其作用嗎?
答:定義了一個函數指針類型的宏,這樣PFUN就表示指向返回值為int,且同時帶2個int 參數的函數指針類型了。
可以用來定義這樣的變量:
比如有個函數為int fun( int x, int y );
PFUN p = fun;
補充::函數指針最大的用處在于它可以被一個模板方法調用,這是我在學java的設計模式時領悟到的.例如,有兩個函數的流程結構完全一致,只是內部調用的具體函數不同,如下所示:
void func1()
{
//一段流程代碼和面向方面的代理,如安全檢查,日志記錄等
int sum = add( x , y);
//一段流程代碼和面向方面的代理,如安全檢查,日志記錄等
}
void func2()
{
//與func1完全相同的一段流程代碼和面向方面的代理,如安全檢查,日志記錄等
int difference = sub( x , y);
//與func1完全相同的一段流程代碼和面向方面的代理,如安全檢查,日志記錄等
}
那么,可以只定義一個函數,如下所示
void func(PFUNC p)
{
//與func1完全相同的一段流程代碼和面向方面的代理,如安全檢查,日志記錄等
int difference = p( x , y);
//與func1完全相同的一段流程代碼和面向方面的代理,如安全檢查,日志記錄等
}
調用程序在調用時,讓參數p分別指向add和sub函數就可以了.
對于許多類似的問題一般從書本上是看不到的,不通過大量的實踐與調試是難以理解和令人困惑的,所以在本文中對于類似上述的C語言問題都將作出詳細的解釋和講解。
總結
以上是生活随笔為你收集整理的经典C语言能力测试题(值得一看)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C/C++ 程序设计员应聘常见面试试题深
- 下一篇: 二进制地址的伙伴地址