深入理解指針
指針系列回顧:
【C語言基礎(chǔ)】:深入理解指針(一)
【C語言基礎(chǔ)】:深入理解指針(二)
一、冒泡排序
冒泡排序的核心思想就是:兩兩相鄰的元素進(jìn)行比較。
#include<stdio.h>
void bubble_sort(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
for (j = 0; j < sz - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = 0;
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
int main()
{
int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
可以看到,這段代碼對arr數(shù)組進(jìn)行了排序,但這個代碼還有一些缺陷,那就是無論數(shù)組內(nèi)部的元素是否有序,他都會循環(huán)9次,這樣肯定是不合理的,要進(jìn)行優(yōu)化一下。
我們在bubble_sort函數(shù)的第一層循環(huán)里面定義一個變量flag,進(jìn)入第二層循環(huán)就修改flag的值,第二層循環(huán)結(jié)束時給變量flag來個判斷,如果變量flag沒有發(fā)生改變,說明沒有進(jìn)入第二層循環(huán),也就是說這時數(shù)組里的元素是有序的,就會直接跳出第一層循環(huán)。另外,我們還可以在最外面定義一個全局變量用來計數(shù),每進(jìn)行一次元素交換就會自增1。
#include<stdio.h>
int count = 0;
bubble_sort(int arr[], int sz) //參數(shù)接收數(shù)組元素個數(shù)
{
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int flag = 1; //假設(shè)這?趟已經(jīng)有序了
int j = 0;
for (j = 0; j < sz - i - 1; j++)
{
count++;
if (arr[j] > arr[j + 1])
{
flag = 0; //發(fā)?交換就說明,?序
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
if (flag == 1) //這?趟沒交換就說明已經(jīng)有序,后續(xù)?序排序了
break;
}
}
int main()
{
int arr[] = { 0,9,8,6,5,3,1,2,4,7 };
int sz = sizeof(arr) / sizeof(arr[0]); // 求出數(shù)組中的元素個數(shù)
bubble_sort(arr, sz);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
printf("%d\n", count);
return 0;
}
運(yùn)行之后可以發(fā)現(xiàn),代碼的運(yùn)行效率明顯提升了,理論來說上述數(shù)組元素在未優(yōu)化的代碼下運(yùn)行是要進(jìn)行45次交換的,現(xiàn)在明顯次數(shù)減少了。
二、二級指針
通過前面的知識我們知道,指針變量也是一個變量,只要是一個變量就會有地址,那么,指針變量的地址放在哪里呢?
我們把存放地址的指針稱為二級指針,也就是指針的指針
#include<stdio.h>
int main()
{
int a = 10;
int* pa = &a;
int** ppa = &pa;
return 0;
}
而三級指針就是存放二級指針變量的地址,四級指針、五級指針以此類推…
對于二級指針的運(yùn)算有:
- *ppa通過對ppa進(jìn)行解引用,就可以找到pa,*ppa其實訪問的就是pa。
int b = 20;
*ppa = &b; // 等價于pa = &b
- **pa先通過*ppa找到pa,然后對pa進(jìn)行解引用操作:*pa,找到的就是a。
**ppa = 30;
//等價于*pa = 30;
//等價于a = 30;
三、指針數(shù)組
首先我們要弄懂一個問題:指針數(shù)組到底是一個指針還是一個數(shù)組?
這里我們可以類比一下:
整數(shù)數(shù)組:就是一個存放整型的數(shù)組。
字符數(shù)組:就是一個存放字符的數(shù)組。
那指針數(shù)組呢?沒錯,就是存放指針的數(shù)組。
指針數(shù)組里的每個元素都是用來存放地址(指針)的。
如下圖:
通過這張圖可以看到,指針數(shù)組里的每一個元素都是一個指針,而這里面的每一個指針又可以指向一塊區(qū)域。
3.1 指針數(shù)組模擬二維數(shù)組
#include<stdio.h>
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 2,3,4,5,6 };
int arr3[] = { 3,4,5,6,7 };
//數(shù)組名是數(shù)組首元素的地址,類型是int*的,就可以存放在parr數(shù)組中
int* parr[] = { arr1, arr2, arr3 };
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 5; j++)
{
printf("%d ", parr[i][j]);
}
printf("\n");
}
return 0;
}
parr[i]是訪問parr數(shù)組的元素,parr[i]找到的數(shù)組元素指向了整型?維數(shù)組,parr[i][j]就是整型?維數(shù)組中的元素。
注意:這只是利用指針數(shù)組模擬的二維數(shù)組,并非是真的二維數(shù)組,因為每一行的地址并非連續(xù)的。
四、字符指針變量
在指針的類型中我們知道有一種指針類型為字輔指針char*
一般使用:
#include<stdio.h>
int main()
{
char ch = 'w';
char* pc = &ch;
*pc = 'w';
return 0;
}
還有一種使用方式如下:
#include<stdio.h>
int main()
{
const char* pc = "hello world";
printf("%s\n", pc);//這里是把一個字符串放到pc指針變量里了嗎?
return 0;
}
注意:這里const char* pc = “hello world”; 特別容易讓人認(rèn)為是把字符串hello world放到字符指針pc里了,但其實本質(zhì)上是字符串hello world 首字符的地址放到了pc中。
上面的代碼的意思是把一個常量字符串的首字符h的地址存放到指針變量pc中。
下面是一道和字符串相關(guān)的題,我們可以學(xué)一下:
#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"); // 序號1
else
printf("str1 and str2 are not same\n"); // 序號2
if (str3 == str4)
printf("str3 and str4 are same\n"); // 序號3
else
printf("str3 and str4 are not same\n"); // 序號4
return 0;
}
運(yùn)行之后我們會發(fā)現(xiàn),打印的是序號2和序號3的語句,這是為什么呢?
這里的str3和str4指向的是同一個常量字符串。C/C++會把常量字符串存儲到一個單獨的內(nèi)存區(qū)域,當(dāng)幾個指針指向同一個字符串的時候,它們實際會指向同一塊內(nèi)存。但是用相同的常量字符串去初始化不同的數(shù)組的時候就會開辟出不同的內(nèi)存塊。所以str1和str2不同,str3和str4相同。
五、數(shù)組指針變量
5.1 數(shù)組指針變量是什么?
上面在學(xué)指針數(shù)組的時候我們知道,指針數(shù)組是數(shù)組元素為指針的數(shù)組。那么數(shù)組指針是什么呢?
上面學(xué)習(xí)指針數(shù)組的時候類比了一下,那么這里不妨也來類比一下:
- 整型指針變量:int * pint; 存放的是整型變量的地址,能夠指向整形數(shù)據(jù)的指針。
- 浮點型指針變量:float * pf; 存放浮點型變量的地址,能夠指向浮點型數(shù)據(jù)的指針。
那么數(shù)組指針就是存放數(shù)組的地址,能夠指向數(shù)組數(shù)據(jù)的指針變量。
我們判斷一下下面那個是數(shù)組指針
int *p1[10];
int (*p2)[10];
int * p1[10]; 是一個指針數(shù)組,是 10 個整型指針的數(shù)組。
int ( * p2)[10]; 是數(shù)組指針,表示一個指向包含 10 個整型數(shù)據(jù)的數(shù)組的指針。因為 p2 是一個指針,所以 p2 是一個指針類型。
數(shù)組指針變量
int (*p2)[10];
這里p會先和 * 號結(jié)合,說明p是一個指針變量,然后指向的是一個大小為10個整型數(shù)據(jù)大小的數(shù)組,所以p是一個指針,指向一個數(shù)組,叫數(shù)組指針。
注意:[]的優(yōu)先級是高于 * 號的,所以必須要加上()來保證 p會先和 * 結(jié)合。
5.2 數(shù)組指針變量的初始化
數(shù)組指針變量是用來存放數(shù)組地址的,那怎么獲得數(shù)組的地址呢?其實就是我們之前學(xué)的 &數(shù)組名。
int main()
{
int arr[10] = { 0 };
&arr; //得到的就是數(shù)組的地址
return 0;
}
如果要存放個數(shù)組的地址,就得存放在數(shù)組指針變量中,如下:
int main()
{
int arr[10] = { 0 };
int(*pa)[10] = &arr;
return 0;
}
在調(diào)試的過程中我們也可以看到 &arr 和pa的類型是完全一致的。
數(shù)組指針類型解析:
int (*p) [10] = &arr;
| | |
| | |
| | | p指向數(shù)組的元素個數(shù)
| p是數(shù)組指針變量名
p指向的數(shù)組的元素類型
六、二維數(shù)組傳參的本質(zhì)
有了數(shù)組指針的理解,我們就能夠講?下二維數(shù)組傳參的本質(zhì)了。
過去我們有一個二維數(shù)組的需要傳參給?個函數(shù)的時候,我們是這樣寫的:
#include<stdio.h>
void test(int a[3][5], int r, int c)
{
int i = 0;
int j = 0;
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
test(arr, 3, 5);
return 0;
}
這里實參是二維數(shù)組,形參也寫成?維數(shù)組的形式,那還有什么其他的寫法嗎?
首先我們再次理解?下二維數(shù)組,二維數(shù)組其實可以看做是每個元素是?維數(shù)組的數(shù)組,也就是?維數(shù)組的每個元素是?個?維數(shù)組。那么?維數(shù)組的首元素就是第一行,是個?維數(shù)組。
如下圖:
所以,根據(jù)數(shù)組名是數(shù)組首元素的地址這個規(guī)則,?維數(shù)組的數(shù)組名表示的就是第一行的地址,是?維數(shù)組的地址。根據(jù)上面的例子,第一行的?維數(shù)組的類型就是 int [5] ,所以第一行的地址的類型就是數(shù)組指針類型 int(*)[5] 。那就意味著?維數(shù)組傳參本質(zhì)上也是傳遞了地址,傳遞的是第一行這個?維數(shù)組的地址,那么形參也是可以寫成指針形式的。如下:文章來源:http://www.zghlxwxcb.cn/news/detail-838292.html
#include<stdio.h>
void test(int(*p)[5], int r, int c)
{
int i = 0;
int j = 0;
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
{
printf("%d ", *((*p + i) + j));
}
printf("\n");
}
}
int main()
{
int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
test(arr, 3, 5);
return 0;
}
總結(jié):二維數(shù)組傳參,形參的部分可以寫成數(shù)組,也可以寫成指針形式。文章來源地址http://www.zghlxwxcb.cn/news/detail-838292.html
到了這里,關(guān)于【C語言基礎(chǔ)】:深入理解指針(三)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!