日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C与指针、C陷阱与缺陷

發布時間:2025/3/21 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C与指针、C陷阱与缺陷 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

遺留問題:
P15理解函數聲明
P39指針與數組

1、單/多字符符號—->貪心法
a+++++b?

【先了解a++與++a的實現原理】

//首先對于i++的實現是:(此時返回的是臨時對象)int temp; temp = i; i = i+1; return temp; //而++i的實現是: i = i+1; return i;

含義:等價于((a++)++)+b,但是編譯失敗,因為((a++)++)+b中先執行a++返回的結果不能作為左值,因此編譯失敗。

【總結】i++不能作為左值,++i可以作為左值
再例:
int main()
{
int d = 0,x = 0;
d = x+++2; //執行結果等價于 d = x+2; x++;
x++ = 2; //編譯失敗,x++不能作為左值
++x = 2; //編譯成功,++x能作為左值
}

2、
單引號:引起來的一個字符實際上代表一個整數(整數值對應于該字符在編譯器采用的字符集中的序列值)。
雙引號:引起來的字符串代表一個指向無名數組起始字符的指針。
3、

int a = 010; //表示8進制的數。

4、運算符的優先級和結合性
【注】
自右向左的運算符:單目運算符、條件運算符?:、賦值運算符=
優先級順序:單目、算數、移位、關系(比較)、位、邏輯、三目、賦值、逗號。
5、多寫分號

if(a==0); //此處多了一個分號,編譯成功a=1;//等價于下面的語句if(a==0) {}a=1;

6、if-else配對問題
else始終與同一對括號內最近的未匹配的if結合。
7、C語言允許初始化列表出現多余的逗號。例如:int days[] = {1,2,3,};
作用:據說初衷是為了方便自動代碼生成工具, 實際上可以說是一處設計失誤,代碼自動生成可以用啊。 你可以寫一個代碼,幫你自動生成源代碼。 這時候,就不用考慮各種格式問題,每一次輸出都是 “%d, “這種類型咯。
8、數組名a與&a
【注】一個數組只需要知道兩點:數組的大小,數組的首地址。

//(一) int a[] = {0,1,2}; int *p = &a; //編譯錯誤 int *p = a; //正確 因為p是一個指向int類型的指針,類型是int*; 而&a表示指向數組的指針,類型是int (*)[3]。 它們類型不匹配! //(二) //a+1表示的是數組第一個元素地址,&a+1表示的是跨過a數組的下一個地址 其實&a和a的值倒是完全一樣的,都是下標為0的元素的地址,關鍵在于它們的作用域不同!(如圖下所示)


(三)多維數組指針的定義

int array[12][31]; int (*P)[31] = array; //True int *p = array; // 無法從“int [12][31]”轉換為“int *” int *p = &array; // 無法從“int (*)[12][31]”轉換為“int *”

9、malloc給數組分配多大的空間?
char *r = malloc(strlen(array)+1); //注:此處必須加1.
10、數組名做形參,則數組名會立刻被轉化為指向給數組第一個元素的指針。
也就是說,下面兩種寫法等價:

int strlen(char s[]) {} int strlen(char *s) {}

再例:

void str(int s[]) {cout<<sizeof(s)<<endl; // 4 因為數組名退化成指針cout<<s[0]<<endl; // 1,但是下標訪問[]還可以使用 } int main() { int array[12] = {1,2,3};str(array);return 0; } char st[] = "Hello";printf("%s",st); //打印Hello,因為printf中的數組名st做參數,退化成指針。

11、

//case 1: int i = 0; while(i < n)y[i] = x[i++]; //case 2: int i = 0; while(i < n)y[i++] = x[i]; //case 3: int i = 0; while(i < n) {y[i] = x[i];i++; } //case 4: for(int i = 0;i<n;i++ )y[i] = x[i]; /* case 1、2是錯誤寫法,不要這么寫!case 3、4正確! 【注】求值順序在作怪。 */ 12、整數溢出 對于加法運算,怎么進行溢出檢查,有下面兩種形式:

INT_MAX是已定義的最大整數值。
//①
if((unsigned)a+(unsigned)b > INT_MAX)
complain();
//②
if(a > INT_MAX - b)
complain();

12extern關鍵字 **在一個源文件里定義了一個數組:char a[6];** **在另外一個文件里用下列語句進行了聲明:extern char *a;這樣可以么?** 不可以,程序運行時會告訴你非法訪問。原因在于,指向類型T的指針并不等價于類型T的數組。extern char *a聲明的是一個指針變量而不是字符數組,因此與實際的定義不同,從而造成運行時非法訪問。應該將聲明改為extern char a[ ] 【結論】這提示我們,在使用extern時候要嚴格對應聲明時的格式,在實際編程中,這樣的錯誤屢見不鮮。 13、命名沖突與static修飾符 static修飾符在C語言中,與extern作用相反,它把變量/函數封裝在一個.cpp文件中,使之對外界.cpp文件不可見。 14

//讀入、處理、打印剩余的行
while(get(input)!=NULL)
{
printf(“%s”,input);
}

【介紹gets函數】 gets從標準輸入設備讀字符串函數。可以無限讀取,不會判斷上限,以回車結束讀取,所以程序員應該確保buffer的空間足夠大,以便在執行讀操作時不發生溢出。 從stdio流中讀取字符串,直至接受到換行符或EOF時停止,并將讀取的結果存放在buffer指針所指向的字符數組中。換行符不作為讀取串的內容,讀取的換行符被轉換為‘\0’空字符,并由此來結束字符串。 讀入成功,返回與參數buffer相同的指針;讀入過程中遇到EOF(End-of-File)或發生錯誤,返回NULL指針。所以在遇到返回值為NULL的情況,要用ferror或feof函數檢查是發生錯誤還是遇到EOF。 【printf格式化輸出】 %o八進制 %x十六進制 %g浮點型數據

15、
char: 0~127
signed char: -127~127
unsigned char: 0~255

八進制: 0開頭
十六進制: 0x開頭

16、左移右移位運算符
對于unsigned值執行所有的移位操作符都是邏輯移位(即:補0)。
17、宏定義中的空格

#define f (x) ((x)-1) //中間有空格下面有兩種說法,哪種說法正確:①f(x)代表((x)- 1--->錯誤②f代表(x)((x)- 1--->正確

18、宏定義中用好括弧并不能保證“萬無一失”
例如:
#define max(a,b) ((a)>(b)?(a):(b)
c = ((a)>(b++)?(a):(b++));
//分析:此時b會被相加兩次,造成意想之外的結果,宏出現副作用。
【解決方案】—>用函數代替宏
【總結】在使用宏的時候,如果宏定義中同一個變量出現兩次,那么在使用宏時如果出現++或者–,就容易發生“副作用”,我們要避免這種情況的發生。
19、從用戶態切換到系統態的三個要素:
異常、中斷、系統(內核函數)調用
20、main函數正常退出返回0,異常退出返回-1.
21、gets( 字符數組名 ):把輸入設備中的一行字符串存儲到字符數組中
從“標準輸入”讀取“一行”文本并把它存儲在字符數組中。一行輸入由一串字符組成,以一個換行符結尾。gets函數丟棄換行符,并在該行的末尾存儲一個NUL字節(一個NUL字節是指字節模式為全0的字節,類似與’\0’這樣的字符常量)。
返回非NULL表示讀取成功;
當讀入過程遇到EOF或發生錯誤時,返回NULL。

char input[MAX_INPUT]; while(gets(input)!=NULL)printf("%s\n",input);

【拓展】
puts(string):把字符串string輸出到屏幕
puts()函數用來向“標準輸出設備(屏幕)”寫字符串并換行, 其調用格式為: puts(s);
puts(s) 等效于printf(“%s\n”,s),前提 :s是C風格字符串,最后以’\0’結尾。

說明: (1). puts()函數只能輸出字符串, 不能輸出數值或進行格式變換。 (2). 可以將字符串直接寫入puts("字符串")函數中。如: puts("Hello World"); #include <stdio.h> #include <conio.h> int main(void) { int i; char string[20]; for(i=0;i<10;i++) string[i]='a'; puts(string); getch(); return 0; } 輸出結果:aaaaaaaaaa燙燙燙燙 從此例中可看到puts輸出字符串時要遇到'\0’也就是字符結束符才停止

22、getchar()

int ch; //注意:char ch會出錯 while((ch = getchar())!=EOF)... ...

23、間接運算符 ->和 . (用于訪問變量中指向的的內容的值)
24、指針幾種常見的錯誤用法

int *p; // *p = 100; //非法進行訪問未初始化指針變量p中的內容NULL指針解引用&假設變量a存儲的位置為100 *100 = 25//錯誤用法 *(int*)100 = 25;//正確用法:強制把值100從“整型”轉換為“指向整型的指針”*p++的含義 //不是(*p)++,而是*(p++),因為優先級:后增 > *

25、如果傳遞的參數是數組名,并且在函數中使用下標引用[ ]該數組的參數,那么在函數中對數組元素進行修改實際上修改的是調用程序中的數組元素。(函數將訪問調用程序的數組元素,數組不會被復制),這種行為相當于“傳址調用”。
26、一維數組名的含義
數組名:是指針常量,即數組第一個元素的地址&array[0],它不能被改變,不能被賦值。

如何區分字符數組和字符串常量 char ch[ ] = "Hello World"; //字符數組 char *ch = "Hello World"; //字符串常量 [例1] int a[3] = {1,1,1,1}; //編譯失敗錯誤 error C2078: 初始值設定項太多 [例2] #include <iostream> using namespace std; int main(void) {int a[3] = {1,1,1};for(int i=0;i <=3;i++)cout<<a[i]<<endl;return 0; } //運行結果:1,1,1,-12283912145 [注]:數組的訪問越界沒法被檢查,因為沒有明確的準則。int a[10]; int* p = &a[4]; p[-2] ——> 的含義是什么? //p[-2]等于a[2],分析:偏移量為-2,(在當前p指向的基礎上,向左偏移2個位置) p[2] ——> 的含義是什么?//p[2]等于a[6],分析:偏移量為+2,(在當前p指向的基礎上,向右偏移兩個位置)

總結

以上是生活随笔為你收集整理的C与指针、C陷阱与缺陷的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。