網(wǎng)站首頁 編程語言 正文
1 指針與數(shù)組
- C語言中只有一維數(shù)組。數(shù)組中的元素可以是任意類型的對象,這也是多維數(shù)組構(gòu)建的理論基礎(chǔ)所在
- 對于一個(gè)數(shù)組,我們只能做兩件事:確定該數(shù)組的大小以及獲得該數(shù)組下標(biāo)為0的元素的指針。任何一個(gè)數(shù)組下標(biāo)運(yùn)算都等同于一個(gè)對應(yīng)的指針運(yùn)算。
- 數(shù)組名代表首元素的地址,無法對其進(jìn)行++或者–操作,換句話說,我們無法改變數(shù)組名(表示的值),因?yàn)閿?shù)組名是個(gè)常量,無法進(jìn)行修改。
2 非數(shù)組的指針
下面有一段程序,指出它的錯(cuò)誤:
char *r; r = malloc(strlen(s)+strlen(t)); strcpy(r,s); strcat(r,t);
- malloc有可能無法提供請求的內(nèi)存,這種情況下malloc函數(shù)會通過返回一個(gè)空指針來作為“內(nèi)存分配失敗”事件的信號。
- 給r分配的內(nèi)存在使用完畢后應(yīng)該及時(shí)釋放。
- 前面的例程在調(diào)用malloc函數(shù)時(shí)并未分配足夠的內(nèi)存,因?yàn)樽址€包含結(jié)束標(biāo)志'\0'。
3 作為參數(shù)的數(shù)組聲明
1.下面列舉的兩種寫法是等價(jià)的:
char hello[] = "hello"; printf("%s\n",hello);//寫法1 printf("%s\n",&hello);//寫法2
原因:數(shù)組名hello代表數(shù)組hello首元素的地址。
2.下面的兩種寫法是等價(jià)的:
int strlen(char s[]) { /*具體內(nèi)容*/ } int strlen(char *s) { /*具體內(nèi)容*/ }
注意下面的兩種寫法:
extern char *hello; extern char hello[];
這兩種寫法雖然是都是正確的,但是不同的形式傳遞給我們的意思卻是完全不一致的,我們要根據(jù)具體情況進(jìn)行使用。
4 空指針并非空字符串
注意:空指針不能對其進(jìn)行解引用。
同時(shí)注意不能出現(xiàn)下述寫法:
if(strcmp(p,(char*)0)==0) ···
這種寫法是非法的,原因在于庫函數(shù)strcmp的實(shí)現(xiàn)中會包括一個(gè)操作,用于查看它的指針參數(shù)所指向的內(nèi)容,即對空指針進(jìn)行了解引用。
也不能出現(xiàn)下述寫法:
假設(shè)p是空指針
printf(p); printf("%s",p); //當(dāng)然,這兩種寫法是等價(jià)的
這種行為是未定義的。
5 邊界計(jì)算與不對稱邊界
在我們寫循環(huán)是最好這樣來寫:
int i = 0; for(i = 0;i < 10; i++) ···
這樣寫能夠更好的看出循環(huán)的次數(shù),即10次。
當(dāng)數(shù)組中有10個(gè)元素時(shí),下標(biāo)的取值范圍為0到9,但是當(dāng)我們不需要引用這個(gè)元素時(shí)只需要引用這個(gè)元素的地址時(shí),我們可以這樣寫
int arr[10] = {1,2,3,4,5,6,7,8,9,10}; for(int i = 0;&arr[i]<&(arr[10]);i++) ···
這樣可以順利打印出數(shù)組元素從1到10的數(shù)字,
ANSI C標(biāo)準(zhǔn)明確允許這種用法:數(shù)組中實(shí)際不存在的"溢界"元素的地址位于數(shù)組之外所占內(nèi)存之后,這個(gè)地址可以用于進(jìn)行賦值和比較。當(dāng)然,如果要引用該元素,那就是非法的了。對于實(shí)際去讀取這個(gè)元素的值,這種做法的結(jié)果是未定義的,而且極少有編譯器能偶檢測出這個(gè)錯(cuò)誤。當(dāng)然,如果試圖去修改這個(gè)元素,必然會導(dǎo)致程序崩潰,屬于非法訪問了!
6 求值順序
C語言中只有四個(gè)運(yùn)算符(&&、||、?:和,)存在規(guī)定的求值順序。==運(yùn)算符&&和運(yùn)算符||首先對左側(cè)操作數(shù)求值,只有在需要時(shí)才對右側(cè)操作數(shù)求值。==運(yùn)算符?:有三個(gè)操作數(shù):在a?b:c中。操作數(shù)a首先被求值,根據(jù)a的值再求操作數(shù)b或c的值(此時(shí)b或c兩個(gè)表達(dá)式根據(jù)前面a表達(dá)式的結(jié)果只會執(zhí)行一個(gè))。逗號運(yùn)算符則首先對左側(cè)操作數(shù)求值,然后"丟棄該值",再對右側(cè)操作數(shù)求值。
注意:分割函數(shù)的參數(shù)并非逗號運(yùn)算符。例如,x和y在函數(shù)f(x,y)中的求值順序是未定義的,而在函數(shù)g((x,y))中卻是確定的先x后y的循序。在后一個(gè)例子中,函數(shù)g只有一個(gè)參數(shù)。這個(gè)參數(shù)的值是這樣求得的:先對x求值,然后“丟棄”x的值,接著求y的值。
這種求值順序的存在使得某些“錯(cuò)誤”的程序變?yōu)榱苏_,且在執(zhí)行后得出正確的結(jié)果:
if(count!=0 && sum/count < smallaverage) ···
注意:C語言中其它所有的運(yùn)算符對其操作數(shù)求值的順序是未定義的。特別是,賦值運(yùn)算符并不保證任何求值循序。
例如:下面的這中從數(shù)組x中復(fù)制前n個(gè)元素到數(shù)組y中的做法是不正確的,因?yàn)樗鼘η笾淀樞蜃隽颂嗟募僭O(shè):
i = 0; while(i < n) y[i] = x[i++];
上面的代碼假設(shè)y[i]的地址將在i的自增操作指向之前被求值,但這是不一定的,這依賴于編譯器的具體實(shí)現(xiàn)。同樣,下面的這種寫法也是不正確的:
i = 0; while(i<n) y[i++] = x[i];
修改成下面這種寫法即可正常工作:
i = 0; while(i<n) { y[i] = x[i]; i++; }
當(dāng)然,這種寫法也可以簡寫為:
for(i = 0;i < n;i++) y[i] = x[i];
7 整數(shù)溢出
無符號整數(shù)不會發(fā)生溢出,這是C語言所規(guī)定的,如果結(jié)果大于所能表示的最大值M,則模(M+1),也就是發(fā)生了截?cái)喱F(xiàn)象。
兩個(gè)有符號整數(shù)進(jìn)行相加時(shí)會發(fā)生溢出,而且溢出的結(jié)果是未定義的。
下面是一種錯(cuò)誤的檢查方式:
if(a + b < 0) complain();
因?yàn)楫?dāng)a+b
卻是發(fā)生溢出時(shí),所有關(guān)于結(jié)果如何假設(shè)都不再可靠。
下面是兩種正確的方式:
//方法一: if((unsigned)a + (unsigned) > INT_MAX) complain(); //方法二: if(a > INT_MAX - b) complain()
8 為函數(shù)提供返回值
C語言種常常通過return 返回一個(gè)值來告知操作系統(tǒng)的執(zhí)行是成功還是失敗,典型的處理方案是。返回值為0表示程序執(zhí)行成功,返回值為非0則表示程序執(zhí)行失敗。我們常常會在程序的末尾加上return 0操作。
原文鏈接:https://blog.csdn.net/m0_57304511/article/details/123509516
相關(guān)推薦
- 2022-11-17 使用flutter的showModalBottomSheet遇到的坑及解決_Android
- 2022-12-15 詳解Golang如何比較兩個(gè)slice是否相等_Golang
- 2022-10-01 python3中_from...import...與import?...之間的區(qū)別詳解(包/模塊)_
- 2021-12-10 linux系統(tǒng)文件共享samba配置教程_Linux
- 2022-10-30 Android?動(dòng)態(tài)加載?so實(shí)現(xiàn)示例詳解_Android
- 2022-06-29 超級詳細(xì)的nginx負(fù)載均衡配置_nginx
- 2022-07-10 query類型對應(yīng)的請求方式params
- 2022-07-11 Python如何獲取多線程返回結(jié)果_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支