點(diǎn)擊這里訪問我的博客主頁~~
對(duì)指針概念還不太清楚的點(diǎn)擊這里訪問上一篇指針初階2.0
上上篇指針初階1.0
謝謝各位大佬的支持咯
今天我們一起來學(xué)習(xí)指針進(jìn)階內(nèi)容
一、指針變量
指針變量有字符指針變量,數(shù)組指針變量和函數(shù)指針變量
1、字符指針變量
char* 叫做字符指針
一般這么來使用:通過指針存儲(chǔ)指針后解引用訪問
int main()
{
char c = 'a';
char* p = &c;
*p = 'a';
return 0;
}
另一種使用方式:
將字符串首字符h的地址放入pstr指針當(dāng)中
int main()
{
const char* pstr = "hello world";
printf("%s\n", pstr);
return 0;
}
我在學(xué)習(xí)過程中,我的老師給我們講了這么一道題
#include <stdio.h>
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;
}
程序的輸出結(jié)果是:
官方解釋:
C/C++會(huì)把常量字符串存儲(chǔ)到單獨(dú)的?個(gè)內(nèi)存區(qū)域,當(dāng)?個(gè)指針指向同?個(gè)字符串的時(shí)候,他們實(shí)際會(huì)指向同?塊內(nèi)存。但是?相同的常量字符串去初始
化不同的數(shù)組的時(shí)候就會(huì)開辟出不同的內(nèi)存塊。
分析:
我們可以看到字符串是一樣的,為hello world,str1和str2不同,str3和str4相同,我們可以看到str3和str4的char*有const修飾,str1和str2沒有,因此我們得出的結(jié)論就是:有const修飾的字符串str3和str4,計(jì)算機(jī)會(huì)將其認(rèn)為是一種字符常量,相同的常量會(huì)被計(jì)算機(jī)存放到同一個(gè)地址里,所以二者相同;str1和str2是變量,被存放再不同的地址里邊了,所以兩者不同(這也優(yōu)化了底層的運(yùn)行,其實(shí)計(jì)算機(jī)每一種規(guī)則都是為了簡化過程,減少資源的浪費(fèi))
2、數(shù)組指針變量
①數(shù)組指針變量的定義
數(shù)組指針變量是指針而不是數(shù)組,其中存放的是數(shù)組的地址,用以指向數(shù)組
數(shù)組指針變量的形式:
int (*p)[5];
前面是數(shù)據(jù)類型:int,char,short等,是由數(shù)組類型來決定的,后邊的 [ ] 里面的數(shù)字自然就是數(shù)組中有幾個(gè)元素我們把 * 和 p 用括號(hào)括起來,表示這是一個(gè)指針,如果不括起來的話:
int* p[5];
這樣p會(huì)與 [ ] 率先結(jié)合,這樣p就不是一個(gè)數(shù)組指針變量了
②數(shù)組指針變量的初始化
int arr[10] = {0};
int(*p)[10] = &arr;
用數(shù)組地址來初始化,注意:用&arr來初始化
3、函數(shù)指針變量
①函數(shù)指針變量的地址
每一個(gè)數(shù)據(jù)都有自己的地址,那么函數(shù)也有自己的地址嗎,我們來看一下
#include <stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
printf("test: %p\n", test);
printf("&test: %p\n", &test);
return 0;
}
運(yùn)行結(jié)果:
我們發(fā)現(xiàn)函數(shù)是有地址的,并且函數(shù)名是可以表示地址的,即在使用函數(shù)地址時(shí),可以只寫函數(shù)名
②函數(shù)指針變量的定義
int (*pf) (int,int);//標(biāo)準(zhǔn)形式
int (*) (int, int);//函數(shù)指針變量pf的類型
這里最前邊也是數(shù)據(jù)類型,為函數(shù)返回?cái)?shù)據(jù)的類型,括號(hào)里為變量的類型以及數(shù)量,有幾個(gè)變量就寫幾個(gè)其相對(duì)應(yīng)的數(shù)據(jù)類型將 * 與 pf 在括號(hào)里括起來原因與上邊數(shù)組指針變量相同,都是為了讓 * 與 pf 結(jié)合
③使用函數(shù)指針變量
加法函數(shù)
#include <stdio.h>
int Add(int x, int y)
{
return x + y;
}
int main()
{
int(*pf)(int, int) = Add;
printf("%d\n", (*pf)(1, 1));
printf("%d\n", pf(2, 3));//函數(shù)名可以做地址
return 0;
}
運(yùn)行結(jié)果:
二、函數(shù)指針數(shù)組
顧名思義,就是儲(chǔ)存函數(shù)指針的數(shù)組
這樣來定義:
int (*parr1[5])();
最前面自然是返回的數(shù)據(jù)類型,最后的括號(hào)里是函數(shù)的輸入數(shù)據(jù),[5]代表數(shù)組中有5個(gè)函數(shù)指針用括號(hào)把*parr1[ ]括起來,表示先結(jié)合
類型為
int (*)()
三、二維數(shù)組傳參的本質(zhì)
1、二維數(shù)組的傳參本質(zhì)
二維數(shù)組傳參本質(zhì)上也是傳遞了地址,傳遞的是第一行這個(gè)一維數(shù)組的地址
通過以前學(xué)的內(nèi)容,我們可以實(shí)現(xiàn)一維數(shù)組打印用指針來實(shí)現(xiàn),那么二維數(shù)組是幾個(gè)一維數(shù)組的組合,指針能表示嗎?答案是可以的。
#include <stdio.h>
void func(int(*p)[5], int a, int b)
{
int i = 0;
int j = 0;
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
printf("%d ", *(*(p + i) + j));
//這里的p+i,當(dāng)i=1時(shí),跳過一行,即一個(gè)一維數(shù)組,地址為指向數(shù)組的首元素,*(p+i)為一個(gè)指針,它在定義或者說未解引用之前和p+i是一樣的,都是地址,最外面的*是解引用
}
printf("\n");
}
}
int main()
{
int arr[3][5] = { {1,2,3,4,5}, {6,7,8,9,10},{11,12,13,14,15} };
func(arr, 3, 5);
return 0;
}
這里我們利用func函數(shù)和循環(huán)的方式,*p表示的就是arr[3][5]里邊的其中一個(gè)[5]
2、二維數(shù)組的應(yīng)用————轉(zhuǎn)移表
#include <stdio.h>
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;
}
//定義四種函數(shù)
void menu()
{
printf("**************************************************\n");
printf("******** 1.add 2.sub *******************\n");
printf("******** 3.mul 4.div *******************\n");
printf("**************** 0.exit ************************\n");
printf("**************************************************\n");
}
//打印一個(gè)菜單函數(shù)
int main()
{
int x = 0;
int y = 0;
int input = 1;
int(*p[5])(int x,int y) = {NULL,add,sub,mul,div};
//首位放NULL,那么可以從1開始訪問函數(shù)指針,當(dāng)然也可以不放,但這么放更好,可以繼續(xù)往下看,看看為什么這么放更好
menu();
do
{
scanf("%d", &input);
if (input >= 1 && input <= 4)
{
printf("請(qǐng)輸入->");
scanf("%d %d", &x, &y);
printf("%d\n", (*p[input])(x, y));
//這里input就不會(huì)為零,whlie也會(huì)繼續(xù)運(yùn)行,我們寫代碼時(shí)要考慮上下不干擾的一致性
}
else if (input == 0)
{
printf("退出\n");
}
else
{
printf("請(qǐng)重新輸入\n");
}
} while (input);
return 0;
}
四、typedef 關(guān)鍵字講解
typedef 是C語言中用來重命名的一個(gè)關(guān)鍵字,對(duì)象是類型
比如說
unsigned int
有點(diǎn)長,用的時(shí)候?qū)懫饋肀容^麻煩
typedef unsigned int a;
現(xiàn)在就可以用a來表示unsigned int了
#include <stdio.h>
int main()
{
typedef unsigned int a;
a c = 10;
printf("%d", c);
return 0;
}
一個(gè)挺有意思的關(guān)鍵字,在以后工作和學(xué)習(xí)中,我們可以早早定義好比較常用的類型,提高工作效率
但是在其使用時(shí),數(shù)組指針和函數(shù)指針的重命名和上述方法有一些不同:
typedef int* p;//正常的普通的指針,定義方法與上述相同
typedef int(*p)[5]; //重命名數(shù)組指針
typedef void(*p)(int);//重命名函數(shù)指針
//新的類型名必須在*的右邊
歡迎大家交流,給出寶貴的意見文章來源:http://www.zghlxwxcb.cn/news/detail-837378.html
今天就到這里啦~文章來源地址http://www.zghlxwxcb.cn/news/detail-837378.html
到了這里,關(guān)于【C語言】指針超級(jí)無敵金剛霹靂進(jìn)階(但不難,還是基礎(chǔ))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!