?作者:@平凡的人1
?專欄:《C語言從0到1》
?一句話:凡是過往,皆為序章
?說明: 過去無可挽回, 未來可以改變
??感謝您的點贊與關(guān)注,同時歡迎各位有空來訪我的??平凡舍
??前言
回想之前,我們學了指針的一些基礎(chǔ)?? 指針與結(jié)構(gòu)體
我們知道了指針的概念:
指針就是個變量,用來存放地址,地址唯一標識一塊內(nèi)存空間。
指針的大小是固定的4/8個字節(jié)(32位平臺/64位平臺)。
指針是有類型,指針的類型決定了指針的±整數(shù)的步長,指針解引用操作的時候的權(quán)限。
指針的運算。
有了前面的一些指針的基礎(chǔ)之后呢,我們將從這篇博客開始,開始一起探究指針的高級主題:指針的進階,將通過不止一篇的博客講完這部分的內(nèi)容,下面一起來看一看>??
??字符指針
在指針的類型中我們知道有一種指針類型為字符指針 char* ;
基本的使用方式:
int main()
{
char ch = 'w';
char *pc = &ch;
*pc = 'w';
return 0;
}
另一種方式:
int main()
{
const char* pstr = "hello world.";//這里是把一個字符串放到pstr指針變量里了嗎?
printf("%s\n", pstr);
return 0;
}
不是,這里本質(zhì)是把字符串 hello world. 首字符的地址放到了pstr中了。并不是整個字符串>
好了?,F(xiàn)在我們一起來看一道題:
#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é)果是什么呢?
這時候,你可能會問了:為什么會這樣子?
其實很簡單,這里str3和str4指向的是一個同一個常量字符串。C/C++會把常量字符串存儲到單獨的一個內(nèi)存區(qū)域,當指針指向同一個字符串的時候,他們實際會指向同一塊內(nèi)存。但是用相同的常量字符串去初始化不同的數(shù)組的時候就會開辟出不同的內(nèi)存塊。所以str1和str2不同,str3和str4不同。
??指針數(shù)組
在前面的時候,我們就認識了指針數(shù)組,指針數(shù)組是一個存放指針的數(shù)組。下面,我們再來重新簡單認識一下,這不是今天的重點,下面指針數(shù)組的含義:
int* arr1[10]; //整形指針的數(shù)組
char *arr2[4]; //一級字符指針的數(shù)組
char **arr3[5];//二級字符指針的數(shù)組
有指針數(shù)組,反過來想:那有沒有數(shù)組指針。有的,下面,我們來看看什么是數(shù)組指針??
??數(shù)組指針
數(shù)組指針是指針?還是數(shù)組?
答案是:指針。
整形指針: int * pint; 能夠指向整形數(shù)據(jù)的指針。
浮點型指針: float * pf; 能夠指向浮點型數(shù)據(jù)的指針。
那數(shù)組指針應(yīng)該是:能夠指向數(shù)組的指針.
下面,我們來區(qū)別一下數(shù)組指針:
int *p1[10];//指針數(shù)組
int (*p2)[10];//數(shù)組指針
int (*p)[10];
//解釋:p先和*結(jié)合,說明p是一個指針變量,然后指著指向的是一個大小為10個整型的數(shù)組。所以p是一個指針,指向一個數(shù)組,叫數(shù)組指針。
//這里要注意:[]的優(yōu)先級要高于*號的,所以必須加上()來保證p先和*結(jié)合。
說到指針,那我們離不開一個話題:&數(shù)組名與數(shù)組名。這有什么區(qū)別呢?下面我們一起來探討:
??&數(shù)組名 與 數(shù)組名
int arr[10];
arr是數(shù)組名,數(shù)組名表示數(shù)組首元素的地址。那&arr數(shù)組名是什么意思?
我們來看一小段代碼:
我們知道,可見數(shù)組名和&數(shù)組名打印的地址是一樣的。這是不是說明了這兩個是一樣的???別急著回答,再來看一段代碼:
根據(jù)上面的代碼我們發(fā)現(xiàn),其實&arr和arr,雖然值是一樣的,但是意義應(yīng)該不一樣的。
實際上: &arr 表示的是數(shù)組的地址,而不是數(shù)組首元素的地址。
本例中 &arr 的類型是: int(*)[10] ,是一種數(shù)組指針類型
數(shù)組的地址+1,跳過整個數(shù)組的大小,所以 &arr+1 相對于 &arr 的差值是40。這時候,你可能會問了,這個40是怎么根據(jù)上面算出來的?
??數(shù)組指針的使用
那數(shù)組指針是怎么使用的呢?既然數(shù)組指針指向的是數(shù)組,那數(shù)組指針中存放的應(yīng)該是數(shù)組的地址。
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
int (*p)[10] = &arr;//把數(shù)組arr的地址賦值給數(shù)組指針變量p
//但是我們一般很少這樣寫代碼
return 0;
}
下面。我們來簡單應(yīng)用一下數(shù)組指針的使用:
#include <stdio.h>
void print_arr1(int arr[3][5], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
void print_arr2(int(*arr)[5], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; 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);
//數(shù)組名arr,表示首元素的地址
//但是二維數(shù)組的首元素是二維數(shù)組的第一行
//所以這里傳遞的arr,其實相當于第一行的地址,是一維數(shù)組的地址
//可以數(shù)組指針來接收
print_arr2(arr, 3, 5);
return 0;
}
兩種方式打印的效果是一樣的:
學了指針數(shù)組和數(shù)組指針我們來看一看下面代碼的意思:
int arr[5];//arr是整型數(shù)組
int *parr1[10];//parr1整型數(shù)指針數(shù)組
int (*parr2)[10];//parr2數(shù)組指針
int (*parr3[10])[5];//parr3是存放數(shù)組指針的數(shù)組
??數(shù)組傳參、指針參數(shù)
??一維數(shù)組傳參
我們來仔細看一看下面是否能成功傳參:
#include <stdio.h>
void test(int arr[])//ok?
{
}
//對于arr可以
void test(int arr[10])//ok?
{
}
//對于arr可以
void test(int* arr)//ok?
{
}
//對于arr可以
void test2(int* arr[20])//ok?
{
}
//對于arr2可以
void test2(int** arr)//ok?
{
}
//arr2是首元素的地址,且存放int*,用二級指針存放一級指針的地址可以。
int main()
{
int arr[10] = { 0 };
int* arr2[20] = { 0 };
test(arr);
test2(arr2);
}
??二維數(shù)組傳參
好啦,看完一維數(shù)組的傳參,現(xiàn)在我們來看看二維數(shù)組的傳參能否成功:
void test(int arr[3][5])//ok?
{
//可以
}
void test(int arr[][])//ok?
{
//不可以,行可以省略,列不可以省略
}
void test(int arr[][5])//ok?
{
//可以,列沒有省略
}
//總結(jié):二維數(shù)組傳參,函數(shù)形參的設(shè)計只能省略第一個[]的數(shù)字。
//因為對一個二維數(shù)組,可以不知道有多少行,但是必須知道一行多少元素。
//這樣才方便運算。
void test(int* arr)//ok?
{
//二維數(shù)組的數(shù)組名,表示首元素的地址,其實是第一行的地址
//第一行是一個一維數(shù)組,一維數(shù)組的地址不能放在一級指針里面
//不可以
}
void test(int* arr[5])//ok?
{
//這是一個指針數(shù)組,我們需要一個指針!
//不可以
}
void test(int(*arr)[5])//ok?
{
//這是一個數(shù)組指針,這種寫法是可以的
}
void test(int** arr)//ok?
{
//二維數(shù)組的數(shù)組名,表示首元素的地址,第一行是一個一維數(shù)組
//一維數(shù)組的地址不能放到二級指針上。
//二級指針是專門來放一級指針變量的地址
//不可以
}
int main()
{
int arr[3][5] = { 0 };
test(arr);
}
??一級指針傳參
#include <stdio.h>
void print(int *p, int sz)
{
int i = 0;
for(i=0; i<sz; 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,傳給函數(shù)
print(p, sz);
return 0;
}
這是非常簡單的,但是如果我們反過來想:當一個函數(shù)的參數(shù)部分為一級指針的時候,函數(shù)能接收什么參數(shù)?舉個例子
void test(int *p)
{
}
//test1函數(shù)能接收什么參數(shù)?首先我們知道這個是整型指針
int a = 10;
int *ptr = &a;
test(ptr);//可以
//還可以傳數(shù)組名等
//只要傳出去的本質(zhì)是一級指針便可
??二級指針傳參
#include <stdio.h>
void 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;
}
同樣,這是比較容易理解,我們應(yīng)該反過來想:當函數(shù)的參數(shù)為二級指針的時候,可以接收什么參數(shù)?
test(int**p)
{
}
int *p1;
int**p2;
int* arr[10];//指針數(shù)組
test(&p1);
test(p2);
test(arr);
這里先說到這里,下面我們一起來看看函數(shù)指針,這時候,有人就有疑問了:函數(shù)指針又是什么?
??函數(shù)指針
什么是函數(shù)指針?
數(shù)組指針——指向數(shù)組的指針就是數(shù)組指針
函數(shù)指針——指向函數(shù)的指針就是函數(shù)指針
怎么表示?
前面說到&數(shù)組名與數(shù)組名的區(qū)別,那&函數(shù)名與函數(shù)名有區(qū)別嗎?我們來看一看
結(jié)果是一模一樣的,對于函數(shù)來說,&函數(shù)名和函數(shù)名是一樣的,都是函數(shù)的地址
那函數(shù)指針有什么用呢?
這里間接通過函數(shù)指針調(diào)用函數(shù),原來都是直接調(diào)用函數(shù)。我們今天不是這么用的。這里的*號其實也可以省略的:
這里稍微提一下。我們再來看一看函數(shù)指針的另一個用法:
#include <stdio.h>
int Add(int x, int y)
{
return x + y;
}
void test(int(*pf)(int, int))
{
int a = 3;
int b = 5;
int ret = pf(a, b);
printf("%d", ret);
}
int main()
{
test(Add);
return 0;
}
這里可以達到這樣的效果。文章來源:http://www.zghlxwxcb.cn/news/detail-403021.html
??結(jié)語
好了,關(guān)于指針進階的第一部分就先說到這了,后面會陸續(xù)更新指針進階的一些知識。如果覺得不錯的話,記得點贊??+收藏哦??文章來源地址http://www.zghlxwxcb.cn/news/detail-403021.html
到了這里,關(guān)于【C語言】指針進階:字符指針&&數(shù)組指針&&函數(shù)指針的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!