
📟作者主頁:慢熱的陜西人
🌴專欄鏈接:C語言
📣歡迎各位大佬👍點贊🔥關注🚓收藏,🍉留言
1.字符指針:介紹了指針的一些進階使用,函數指針,函數指針數組,轉移表,內容難度上升。
📣在指針的類型中我們知道有一種指針類型為字符指針 char*
一般用法:
int main()
{char ch = 'w';
char *pc = &ch;
*pc = 'w';
return 0;
}另一種使用方法:
📣代碼 const char* pstr = “hello bit.”; 這里只是將首字符的地址放到了pstr中
int main()
{const char* pstr = "hello bit.";//這里是把一個字符串放到pstr指針變量里了嗎?
printf("%s\n", pstr);
return 0;
}所以有如下的面試題:
int main()
{char str1[] = "hello bit.";
char str2[] = "hello bit.";
const char *str3 = "hello bit.";
const char *str4 = "hello bit.";
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;
}輸出的結果:
str1 and str2 are not same
str3 and str4 are same2.指針數組:📣顧名思義存放指針的數組
例如:
int* arr1[10]; //整形指針的數組
char *arr2[4]; //一級字符指針的數組
char **arr3[5];//二級字符指針的數組3.數組指針:數組指針的定義:指向數組的指針
下面代碼哪個是數組指針?
int *p1[10];
int (*p2)[10];
//p1, p2分別是什么?4.&數組名VS數組名:
- p1則是int型的指針數組
- p2則是int型的數組指針
- 原理是[]的優(yōu)先級比*高所以不帶括號的情況下就會被識別成數組
- 帶上括號就會和解引用操作符結合所以就是數組指針了
結論:打印地址的話數值上是相同的,實際上是兩種不同的類型所以在進行加一時步長不一樣;
(1)相同的點:
打印地址的代碼:
#includeint main()
{int arr[10] = {0};
printf("%p\n", arr);
printf("%p\n", &arr);
return 0;
} 不同的點:
📣原因是:
- &arr和arr數值上相同,但是意義卻不同 &arr表示的是數組的地址(對應之前的兩種特殊情況)。
- arr表示的是數組首元素地址。
- 所以&arr + 1 跳過的是整個數組&arr + 1 和 &arr 的差值是40
#includeint main()
{int arr[10] = {0 };
printf("arr = %p\n", arr);
printf("&arr= %p\n", &arr);
printf("arr+1 = %p\n", arr+1);
printf("&arr+1= %p\n", &arr+1);
return 0;
} 5.數組指針的使用:數組指針指向的是數組,那數組指針中存放的應該是數組的地址
#includevoid print_arr1(int arr[3][5], int row, int col)
{ int i = 0;
for(i=0; ifor(j=0; j printf("%d ", arr[i][j]);
}
printf("\n");
}
}
void print_arr2(int (*arr)[5], int row, int col)
{ int i = 0;
for(i=0; ifor(j=0; j printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main()
{ int arr[3][5] = {1,2,3,4,5,6,7,8,9,10};
print_arr1(arr, 3, 5);
//數組名arr,表示首元素的地址
//但是二維數組的首元素是二維數組的第一行
//所以這里傳遞的arr,其實相當于第一行的地址,是一維數組的地址
//可以數組指針來接收
print_arr2(arr, 3, 5);
return 0;
}
幾個例子:
int arr[5]; //整型數組
int *parr1[10]; //指針數組
int (*parr2)[10]; //數組指針
int (*parr3[10])[5];//數組指針的數組6.數組參數、指針參數:
6.1一維數組傳參:#includevoid test(int arr[])//ok
{}
void test(int arr[10])//ok
{}
void test(int *arr)//ok
{}
void test2(int *arr[20])//ok
{}
void test2(int **arr)//ok
{}
int main()
{int arr[10] = {0};
int *arr2[20] = {0};
test(arr);
test2(arr2);
} 數組傳參:形參可以是數組,也可以是指針
6.2二維數組傳參:void test(int arr[3][5])//ok
{}
void test(int arr[][])//no
{}
void test(int arr[][5])//ok
{}
//總結:二維數組傳參,函數形參的設計只能省略第一個[]的數字。
//因為對一個二維數組,可以不知道有多少行,但是必須知道一行多少元素。
//這樣才方便運算。
void test(int *arr)//no 是一級指針,無法接收數組的指針
{}
void test(int* arr[5])//no 是數組,無法接收指針
{}
void test(int (*arr)[5])//ok 數組指針可以接收
{}
void test(int **arr)//no 二級指針用于接收一級指針的地址與arr不匹配所以不行
{}
int main()
{int arr[3][5] = {0};
test(arr);//因為arr是二維數組,所以arr表示的是第一行的地址
}6.3一級指針傳參:#includevoid print(int *p, int sz)
{int i = 0;
for(i=0; i printf("%d\n", *(p+i));
}
}
int main()
{int arr[10] = {1,2,3,4,5,6,7,8,9};
int *p = arr;
int sz = sizeof(arr)/sizeof(arr[0]);
//一級指針p,傳給函數
print(p, sz);
return 0;
} 函數的形參是一級指針我們可以傳什么參數:
void test1(int *p)
{}
//test1函數能接收什么參數?
int a = 0;
test(&a);//ok
int * ptr = &a;
test(ptr);//ok
int arr[10];
test(arr);//ok
void test2(char* p)
{}
//test2函數能接收什么參數?
//類似上面
//char型變量的地址
//char型數組名或地址6.4二級指針傳參:例如:
#includevoid test(int** ptr)
{printf("num = %d\n", **ptr);
}
int main()
{int n = 10;
int*p = &n;
int **pp = &p;
test(pp);
test(&p);
return 0;
} 當函數的參數為二級指針的時候,可以接收什么參數?
void test(char **p)
{}
int main()
{char c = 'b';
char*pc = &c;
char**ppc = &pc;
char* arr[10];
test(&pc);
test(ppc);
test(arr);//Ok 因為指針數組的數組名就是首元素地址也就是二級指針
return 0;
}7.函數指針:首先看一段代碼:
#includevoid test()
{printf("hehe\n");
}
int main()
{printf("%p\n", test);
printf("%p\n", &test);
return 0;
} 
創(chuàng)建一個函數指針類型:
形式 :返回類型 (指針變量名)(函數參數);*
兩段考基礎的代碼:
//代碼1
(*(void (*)())0)();
//代碼2
void (*signal(int , void(*)(int)))(int);解釋:
//代碼1
0 - int
( void (*)() )0 - 把0當做一個函數的地址
( *( void (*)() )0 )();
//把0直接轉換成一個void (*)()的函數指針,然后去調用0地址處的函數
//代碼2
//上述代碼是一次函數聲明
// //聲明的函數叫:signal
// //signal函數的第一個參數是int類型的
// //signal函數的第二個參數是一個函數指針類型,該函數指針指向的函數參數是int,返回類型是void
// //signal函數的返回類型也是一個函數指針類型,該函數指針指向的函數參數是int,返回類型是void對代碼2的化簡:
typedef void(*pfun_t)(int);
pfun_t signal(int, pfun_t);8.函數指針數組:8.1應用:即存放函數指針的數組
如何定義:
返回類型 ( * 變量名[x] )(形參); // 其中x表示的是數組的大小
例如 返回值為int 無形參的函數的函數指針數組:
int (*parr1[10])();
用途是:轉移表:
應用示例(計算機):
#includeint add(int a, int b)
{return a + b;
}
int sub(int a, int b)
{return a - b;
}
int mul(int a, int b)
{return a*b;
}
int div(int a, int b)
{return a / b;
}
int main()
{int x, y;
int input = 1;
int ret = 0;
int(*p[5])(int x, int y) = {0, add, sub, mul, div }; //轉移表
while (input)
{printf( "*************************\n" );
printf( " 1:add 2:sub \n" );
printf( " 3:mul 4:div \n" );
printf( "*************************\n" );
printf( "請選擇:" );
scanf( "%d", &input);
if ((input<= 4 && input >= 1))
{printf( "輸入操作數:" );
scanf( "%d %d", &x, &y);
ret = (*p[input])(x, y);
}
else
printf( "輸入有誤\n" );
printf( "ret = %d\n", ret);
}
return 0;
} 9.指向函數指針數組的指針:本質上還是一個指針:
如何定義:
返回值類型 (*(*變量名)[數組大小])(形參);
例如:
void test(const char* str)
{printf("%s\n", str);
}
int main()
{//函數指針pfun
void (*pfun)(const char*) = test;
//函數指針的數組pfunArr
void (*pfunArr[5])(const char* str);
pfunArr[0] = test;
//指向函數指針數組pfunArr的指針ppfunArr
void (*(*ppfunArr)[5])(const char*) = &pfunArr;
return 0;
}10.回調函數:回調函數就是一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個
函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數。回調函數不是由該函數
的實現方直接調用,而是在特定的事件或條件發(fā)生時由另外的一方調用的,用于對該事件或條件進
行響應
示例(快排):
int swap_int(const void* a, const void* b)
{return (*(int*)a) - (*(int*)b);
}
qsort(arr, sizeof(int), sizeof(arr) / sizeof(int), swap_int);到這本篇博客的內容就到此結束了。
如果覺得本篇博客內容對你有所幫助的話,可以點贊,收藏,順便關注一下!
如果文章內容有錯誤,歡迎在評論區(qū)指正

你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧
網頁名稱:[C語言]指針進階-創(chuàng)新互聯
鏈接地址:http://www.chinadenli.net/article10/igido.html
成都網站建設公司_創(chuàng)新互聯,為您提供虛擬主機、微信公眾號、定制網站、微信小程序、動態(tài)網站、ChatGPT
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯