目錄
城北ssl適用于網站、小程序/APP、API接口等需要進行數據傳輸應用場景,ssl證書未來市場廣闊!成為成都創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:13518219792(備注:SSL證書合作)期待與您的合作!1.字符指針
1.1字符指針定義
1.2 字符指針用法
2.指針數組
2.1 指針數組定義及使用
3.數組指針
3.1 數組指針定義
3.2 &數組名和數組名?
3.3 數組指針的基本用法
4. 數組參數、指針參數?
5. 函數指針?
5.1 函數指針定義既基本使用
5.2 有趣的代碼?
6. 函數指針數組?
6.1 函數指針數組定義
6.2 函數指針數組用法?
6.3 指向函數指針數組的指針?
7. 回調函數?
7.1 回調函數定義
7.2 回調函數使用?
在初學指針的時候你是否也常常分不清楚 ’指針數組‘ 和 ’數組指針‘ 呢?
結果是指針數組是數組,數組指針是指針,那快來學習一下這篇好文,更深刻的了解吧
前面初階指針中學習了一下指針的基本概念:
1.字符指針 1.1字符指針定義1. 指針就是個變量,用來存放地址,地址唯一標識一塊內存空間。
2. 指針的大小是固定的4/8個字節(jié)(32位平臺/64位平臺)。
3. 指針是有類型,指針的類型決定了指針的+-整數的步長,指針解引用操作的時候的權限。
4. 指針的運算
http://t.csdn.cn/wsHNl??????
在指針類型中我們知道一種指針類型為:char*
1.2 字符指針用法一般情況就是存放字符變量地址的指針
int main() { char a = 'w'; char* pc = &a; return 0; }
除去存放字符變量地址這個用法外還有其他的用法:
首先知道字符串常量:一對雙引號括起來的字符序列
int main() { const char* pc = "abcdef"; //字符串"abcdef"是常量,不可被修改所以加上const修飾 printf("%c\n", *pc); // 'a' printf("%s\n", pc); // "abcdef" return 0; }
這么一串代碼字符指針pc存放的是字符串"abcdef"的首元素地址,所以如果打印一個字符:解引用pc打印結果就是字符串的首元素‘a’,知道了首元素既可通過字符指針pc打印字符串
字符指針經典面試題:題源《劍指offer》
2.指針數組 2.1 指針數組定義及使用int main() { char str1[] = "hello world."; char str2[] = "hello world."; const char* str3 = "hello world."; const char* str4 = "hello world."; if (str1 == str2) printf("str1 and str2 are same\n"); else printf("str1 and str2 are not same\n"); if (str3 == str4) printf("str3 and str4 are same\n"); else printf("str3 and str4 are not same\n"); return 0; }
輸出結果:
str3和str4指向的是一個同一個常量字符串。C/C++會把常量字符串存儲到單獨的一個內存區(qū)域,當幾個指針。指向同一個字符串的時候,他們實際會指向同一塊內存。但是用相同的常量字符串去初始化不同的數組的時候就會開辟出不同的內存塊。所以str1和str2不同,str3和str4不同。
指針數組是一個存放指針的數組。
3.數組指針 3.1 數組指針定義int main() { char* pch[5]; // 字符指針數組 int* parr[5];// 整形指針數組 char** ppch[5]; //二級字符指針數組 return 0; }
指針數組用法:將三個一維數組通過指針變成二維數組并輸出打印
int main() { int arr1[] = { 1,2,3,4,5 }; int arr2[] = { 2,3,4,5,6 }; int arr3[] = { 3,4,5,6,7 }; int* arr[] = { arr1,arr2,arr3 };//定義一個指針數組存放arr1、2、3,的首元素地址 int i = 0; for (i = 0; i< 3; i++) { int j = 0; for (j = 0; j< 5; j++) { // *(arr[i]+j)=arr[i][j] 通過i分別找出arr1、2、3并通過j找出所對于的數 printf("%d ", arr[i][j]); } printf("\n"); } return 0; }
數組指針是指向數組的指針?
3.2 &數組名和數組名?數組指針表示形式:
int main() { int arr[10] = { 0 }; int(*p)[10] = &arr;//取出的arr數組的地址 // 取出arr的地址,元素個數10,每個元素類型為int return 0; }
解釋:p先和*結合,說明p是一個指針變量,然后指著指向的是一個大小為10個整型的數組。所以p是一個指針,指向一個數組,叫數組指針。
這里要注意:[]的優(yōu)先級要高于*號的,所以必須加上()來保證p先和*結合。區(qū)分:指針數組 和 數組指針
3.3 數組指針的基本用法&數組名:取出的是整個數組的地址
數組名:表示的是首元素的地址?
http://t.csdn.cn/Pm7B9
本例中 &arr 的類型是: int(*)[10] ,是一種數組指針類型
數組的地址+1,跳過整個數組的大小,所以 &arr+1 相對于 &arr 的差值是40
4. 數組參數、指針參數?例:將一個整形二維數組中的元素輸出打印
void print1(int arr[3][5],int x,int y) { int i = 0; int j = 0; for (i = 0; i< x; i++) { for (j = 0; j< y; j++) { printf("%d ", arr[i][j]); } printf("\n"); } } void print2(int(*pa)[5], int x, int y) { //int(*pa)[5] 表示指向一個有5個int類型元素的數組,既arr首地址 int i = 0; for (i = 0; i< x; i++) { int j = 0; for (j = 0; j< y; j++) { printf("%d ", (*(pa)+i)[j]);//*(pa)+i==pa[i] } printf("\n"); } } int main() { int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} }; print1(arr,3,5);//arr首元素地址是{1,2,3,4,5} print2(arr,3,5); return 0; }
數組名arr,表示首元素的地址
但是二維數組的首元素是二維數組的第一行
所以這里傳遞的arr,其實相當于第一行的地址,是一維數組的地址
可以數組指針來接收
5. 函數指針? 5.1 函數指針定義既基本使用一維數組傳參
void test1(int arr [])//同樣用整形數組接收 {} void test2(int* str) //用一個同類型指針接收 {} void test3(int arr[5])//同類型同大小接收(數組大小可忽略) {} void test1_1(int* parr[]) //相同整形指針數組接收 {} void test2_2(int** str) //二級指針接收 {} int main() { int arr[5] = { 0 };//一維數組 int* parr[10] = { 0 };//指針數組 test1(arr); test2(arr); test3(arr); test1_1(parr); test2_2(parr); return 0; }
二維數組傳參
void test1(int arr[3][5])//相同類型二維數組 {} void test2(int arr[][5])//二維數組傳參,函數形參的設計只能省略第一個[]的數字。 {} void test3(int(*pa)[5])//用數組指針接收 {} int main() { int arr[3][5] = { 0 }; test1(arr); test2(arr); test3(arr); return 0; }
一級指針傳參
void test(int* p)//同類型指針接收 { int i = 0; for (i = 0; i< 5; i++) { printf("%d ", *(p + i)); } } int main() { int arr[5] = { 1,2,3,4,5 }; int* pa = arr; test(pa); return 0; }
二級指針傳參
void test(int** ppa)//相同類型二級指針接收 {} int main() { int a =5; int* pa = &a; int** ppa = &pa; test(ppa); return 0; }
5.2 有趣的代碼?函數指針:存放函數地址的指針變量
兩個輸出的都是test函數的地址
void test() {} int main() { test(); void (*p)() = &test; //函數指針,存放函數地址 return 0; }
pfun1可以存放。pfun1先和*結合,說明pfun1是指針,指針指向的是一個函數,指向的函數無參數,返回值類型為void。
函數指針基本使用:
int add(int x, int y) { return x + y; } int main() { int a = 0; int b = 0; int(*pa)(int, int) = &add;//存放add函數地址的函數指針 printf("%d\n", (*pa)(10, 20));//直接通過解引用pa操作函數add return 0; }
下面是兩個有趣的代碼,簡述大概意思。來源:《C陷阱與缺陷》?
6. 函數指針數組? 6.1 函數指針數組定義代碼1:
首先看到這么一個復雜的代碼,我們先將其括號配對,使我們能更明確的看出所代表的含義
簡述:將整形0強制 類型轉換成一個參數為無返回類型為void的函數指針地址,既0地址
后調用地址為0的函數。
代碼2:
簡述:
signal是一個函數聲明
signal函數的參數有2個,第一個是int。第二個是函數指針,該函數指針指向的函數的參數是int,返回類型是void
signal函數的返回類型也是一個函數指針:該函數指針指向的函數的參數是int,返回類型是void
函數指針數組:存放函數指針的數組
6.2 函數指針數組用法?int add(int x, int y) { return x + y; } int sub(int x, int y) { return x - y; } int mul(int x, int y) { return x * y; } int div(int x, int y) { return x / y; } int main() { int (*pf[4])(int, int) = { add,sub,mul,div }; return 0; }
pf?先和 [] 結合,說明 pf是數組,數組內容是:int (*) (int ,int );
函數指針數組用途:轉移表?
以計算器為例,函數指針數組用法:
6.3 指向函數指針數組的指針?void mune() { printf("**********************\n"); printf("** 1.add 2.sub **\n"); printf("** 3.mul 4.div **\n"); printf("******* 0.exit *******\n"); } int add(int x, int y) { return x + y; } int sub(int x, int y) { return x - y; } int mul(int x, int y) { return x * y; } int div(int x, int y) { return x / y; } int main() { int n = 0; int x = 0; int y = 0; int(*pf[5])(int, int) = { 0,add,sub,mul,div };//定義5個下標,讓數組下標和菜單選項對應 //函數指針數組:轉移表 do { mune(); printf("請選擇:>"); scanf("%d", &n); if (n >= 1 && n<= 4) { printf("請輸入兩位操作數:>"); scanf("%d %d", &x, &y); printf("%d\n", pf[n](x, y)); } else if (n == 0) { printf("退出\n"); } else { printf("輸入錯誤\n"); } } while (n); return 0; }
存放函數指針數組地址的指針變量
7. 回調函數? 7.1 回調函數定義void test(const char* str) { printf("%s\n", str); } int main() { //函數指針 void(*p)(const char*) = &test; //函數指針的數組 void(*parr[5])(const char*); //指向函數指針數組的指針 void (*(*pfarr)[5])(const char*) = &parr; return 0; }
7.2 回調函數使用?回調函數就是一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數?;卣{函數不是由該函數的實現方直接調用,而是在特定的事件或條件發(fā)生時由另外的一方調用的,用于對該事件或條件進行響應。
void print(char* str) { printf("%s\n", str); } void test(void) { print("hello world!"); } int main() { test(); return 0; }
設定一個通用冒泡排序函數可以排序任意類型:參考函數qsort()?
qsort ()函數詳解:? ? ? ? ? http://t.csdn.cn/xkfQ8http://t.csdn.cn/xkfQ8代碼實現:
//置換
void permute(char* buf1, char* buf2, int width)//類型不同,一個字節(jié)一個字節(jié)進行置換
{
int i = 0;
for (i = 0; i< width; i++)
{
char tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;
}
}
// base:任意類型數組地址,sz:數組長度,width:數組寬度(數組類型),比較參數函數
void bubble_sort(void* base,int sz,int width,int(*cmp)(void* elem1,void*elem2))
{
//冒泡排序
int i = 0;
//趟數
for (i = 0; i< sz-1; i++)
{
//每躺比較的對數
int j = 0;
for (j = 0; j< sz - i - 1; j++)
{
//比較兩個參數
if (cmp((char*)base+width*j, (char*)base+width*(j+1)) >0)//比較該元素和后一個元素大小
//傳參任意類型,可通過一個字節(jié)+寬度就等于該數據類型,一個char類型加上一個int類型就等于跳過一個int類型
{
//置換
permute((char*)base + width * j, (char*)base + width * (j + 1),width);
}
}
}
}
int cmp_int(void* elem1, void* elem2)
{
return *(int*)elem1 - *(int*)elem2;
}
void test(void)
{
int arr[] = { 1,3,5,7,9,2,4,6,8,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
for (i = 0; i< sz; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
test();
return 0;
}
你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧
本文名稱:C語言—指針進階(詳解篇)-創(chuàng)新互聯(lián)
鏈接URL:http://aaarwkj.com/article38/ccjipp.html
成都網站建設公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網站、建站公司、App開發(fā)、標簽優(yōu)化、網站改版、微信小程序
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內容