書中示例:編寫乙個處理陣列的函式,要求該函式能夠返回陣列中所有元素之和。
total=sum(marbles);
這裡的marbles為陣列名,表示首元素的位址
注意:
除了以下兩種情況陣列名表示的不是首元素位址,其餘都是:
1、&陣列名 陣列名不是首元素的位址,表示整個陣列。&陣列名:取出的是整個陣列的位址
2、sizeof(陣列名) 陣列名表示整個陣列 sizeof(陣列名)
所以既然能用陣列名表示位址,那麼也能用陣列名表示指標。
上**:
另一類寫法#include #define size 10
int sum(int* ar, int n);
int main(void)
; long answer;
answer = sum(marbles, size);
printf("the total number of marbles is %ld.\n", answer);
printf("the size of marbles is %zd bytes.\n",
sizeof marbles);
return 0;
} int sum(int* ar, int n)
顯然,執行後效果是一樣的,所以int* ar能表示為int ar#include #define size 10
int sum(int ar, int n);
int main(void)
; long answer;
answer = sum(marbles, size);
printf("the total number of marbles is %ld.\n", answer);
printf("the size of marbles is %zd bytes.\n", sizeof marbles);
return 0;
} int sum(int ar, int n)
執行結果顯示,ar的大小為8位元組,即在該系統中用於儲存位址的記憶體大小為8位元組
兩個重要的符號:
strien是求字串長度的,只針對字串長度,是一種庫函式,使用時必須引用標頭檔案
sizeof計算變數、陣列型別的,大小單位是位元組,是一種操作符
函式處理陣列時必須知道何時開始,何時結束
第一種表達方式是用乙個指標形參標識陣列的開始,用乙個整數形參表明待處理的元素個數
第二種表達方式是分別使用乙個指標形參標識陣列的開始,乙個指標形參指明陣列的結束處int sum(int* ar, int n);
answer = sum(marbles, size);
所以上例也可以寫成:int sump(int * start, int * end);
answer = sump(marbles, marbles + size);//結束處指向陣列最後乙個元素的後面
由於一元運算子*和++的優先順序與++的優先順序相同,所以根據結合律從右往左的規則,所以也可以寫成:#include #define size 10
int sump(int * start, int * end);
int main(void)
; long answer;
answer = sump(marbles, marbles + size);
printf("the total number of marbles is %ld.\n", answer);
return 0;
} int sump(int * start, int * end)
return total;
}
total += *star++;//先把指標指向位置上的值加到total上,然後再遞增指標
字尾的位置影響十分大,上**:
執行結果是;#include int data[2] = ;
int moredata[2] = ;
int main(void)
總結出其中規律就是:*p1 = 100, *p2 = 100, *p3 = 300
*p1++ = 100, *++p2 = 200, (*p3)++ = 300
*p1 = 200, *p2 = 200, *p3 = 301
由以上例子分析可以看出,處理陣列的函式實際使用的是指標作為實參,而函式的編寫可以選擇使用兩種表示法。只不過使用陣列表示法的意圖會更加明顯*p++:先使用指標指向位置上的值,然後再遞增指標
*++p:先遞增指標,再使用遞增指標指向位置上的值
(*p)++:先使用指標指向位置的值,再將該值遞增
在c語言中,ar[i]與(*ar+1)是等價的,只不過當ar為指標變數時,才使用ar++這樣的表示式
指標表示法(尤其是與遞增運算子一起使用時)更加接近機器語言,因此一些編譯器在編譯時能生成效率更高的**
八種操作:
指標函式:返回指標型別的函式#include int main(void)
; int * ptr1, *ptr2, *ptr3;
ptr1 = urn; // 把乙個位址賦給指標
ptr2 = &urn[2]; // 把乙個位址賦給指標
// 解引用指標,以及獲得指標的位址
printf("pointer value, dereferenced pointer, pointer address:\n");
printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %p\n", ptr1, *ptr1, &ptr1);
// 指標加法
ptr3 = ptr1 + 4;
printf("\nadding an int to a pointer:\n");
printf("ptr1 + 4 = %p, *(ptr1 + 4) = %d\n", ptr1 + 4, *(ptr1 + 4));
ptr1++; // 遞增指標
printf("\nvalues after ptr1++:\n");
printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %p\n", ptr1, *ptr1, &ptr1);
ptr2--; // 遞減指標
printf("\nvalues after --ptr2:\n");
printf("ptr2 = %p, *ptr2 = %d, &ptr2 = %p\n", ptr2, *ptr2, &ptr2);
--ptr1; // 恢復為初始值
++ptr2; // 恢復為初始值
printf("\npointers reset to original values:\n");
printf("ptr1 = %p, ptr2 = %p\n", ptr1, ptr2);
// 乙個指標減去另乙個指標
printf("\nsubtracting one pointer from another:\n");
printf("ptr2 = %p, ptr1 = %p, ptr2 - ptr1 = %td\n", ptr2, ptr1, ptr2 - ptr1);
// 乙個指標減去乙個整數
printf("\nsubtracting an int from a pointer:\n");
printf("ptr3 = %p, ptr3 - 2 = %p\n", ptr3, ptr3 - 2);
return 0;
}
另一種十分類似的寫法(但這種寫法是不對的):char*getwork(char c)
}int main(void)
不要返回區域性變數的指標(陣列)char*getwork(char c)
}int main(void)
在該例中,str1是區域性變數,這個字元陣列在子程式結束後,它對應的儲存空間會立即釋放
函式指標:指向函式起始位址的指標
函式指標定義:
函式返回型別名(指標變數名)(函式形參型別列表)
如:int(fptr)(int,int);
指標函式的使用:
1、指標變數名=被指向函式名;
如:fptr=maxx;
2、函式呼叫:指標變數名(函式呼叫時的實際引數);
如:int x=fptr(5,8);
看不懂?上**:
函式名等於函式的位址。通過fp=square;語句使得fp指向函式的入口,因此通過fp指標就能找到函式squar的**存放的位置,從而呼叫並執行這段**。#includeint square(int num)
int main(void)
陣列越界那點事兒
c語言中,函式在呼叫乙個陣列時,如果區域性陣列寫入產生了越界,則會導致函式的返回位址被覆蓋掉,從而破壞呼叫函式的棧幀。而陣列越界寫入就是破壞堆疊的原因有以下兩點 2 陣列的存放是從記憶體低位向高位存放。所以,如果陣列大小是4位元組,如果越界寫入,就會向上破壞相鄰高位記憶體中儲存的資料,可能是前面的區...
陣列指標和指標陣列 函式指標和指標函式
一 陣列指標與指標陣列 1,指標陣列 所謂指標陣列,就是指標組成的陣列,即陣列的元素為指標 int pa size size為元素數目,元素的值為int型別的指標 2,陣列指標 所謂陣列指標,就是指向陣列的指標,即其是乙個指標,指向陣列。int pa size size為陣列的元素數目,pa指向乙個...
Switch和Enum的那點事兒
類之間傳遞引數呼叫方法時,當引數不同是,可以考慮用列舉做引數,被呼叫類中用switch case判斷呼叫 列舉public enum bindtype 列舉元素的預設基礎型別為 int。預設情況下,第乙個列舉數的值為 0,後面每個列舉數的值依次遞增 1。enum days 列舉數可以具有重寫預設值的...