欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言進階學(xué)習(xí)之指針

 更新時間:2021年09月29日 08:47:24   作者:和太陽肩并肩的老楊  
關(guān)于指針,其是C語言的重點,C語言學(xué)的好壞,其實就是指針學(xué)的好壞。其實指針并不復(fù)雜,學(xué)習(xí)指針,要正確的理解指針,本片文章能給就來學(xué)習(xí)一下

1.指針概念回顧

指針的基本概念:

指針是一個變量,用來存放地址,地址唯一標(biāo)識一塊內(nèi)存空間。指針的大小是固定的4/8個字節(jié)(32位平臺/64位平臺)。指針是有類型,指針的類型決定了指針的±整數(shù)的步長,指針解引用操作的時候的權(quán)限。不能對沒有初始化的指針或者是空指針進行間接訪問

2.字符指針

指針類型為 char* 的指針就是字符指針

字符指針指向的對象的類型為字符型

一般使用方法:

    char ch = 'a';
	char* p = &ch; //取ch的地址放到指針變量p中

另外一種常見使用方法:

char* p2 = "bcdef"; 

對于第二種使用方法我們需要注意的是

p2實際存放的只是字符串首字符的地址,即p2存放的是字符b的地址。

在這里插入圖片描述

我們來看一道經(jīng)典的面試題:

#include <stdio.h>
int main()
{
	char str1[] = "hello yang.";
	char str2[] = "hello yang.";
	char* str3 = "hello yang.";
	char* str4 = "hello yang.";
	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指向的都是字符串H的地址

當(dāng)指針指向同一個字符串的時候,它們實際會指向同一塊內(nèi)存。但是用相同的常量字符串去初始化不同的數(shù)組的時候就會開辟出不同的內(nèi)存塊。

因此它的答案為

在這里插入圖片描述

3.數(shù)組指針和指針數(shù)組

指針數(shù)組是一個存放指針的數(shù)組

例如

int* arr1[10]; //整形指針的數(shù)組
char *arr2[4]; //一級字符指針的數(shù)組
char **arr3[5]; //二級字符指針的數(shù)組

3.1數(shù)組指針的含義

數(shù)組指針是指針?還是數(shù)組?

答案是:指針。

int *p1[10];
int (*p2)[10];
//p1, p2分別是什么?

這里就不得不談?wù)摰絻?yōu)先級了,優(yōu)先級從大到小的順序為: “( )” > “[ ]” > “ * ”

首先看int *p1[10]; , 由于[ ]的優(yōu)先級大于*,因此p1先與“[” 結(jié)合,故而p1首先它是一個數(shù)組,它是一個存放了10個指針變量的數(shù)組。

再來看int (*p2)[10];, 由于()的優(yōu)先級大于 [ ], 先看()里的,p2與 * 結(jié)合,故而篇是一個指針,它指向了一個存放了10個整型的數(shù)組

3.2&數(shù)組名vs數(shù)組名

對于下面這個代碼

#include <stdio.h>
int main()
{
    int arr[5] = {0};
    printf("%p\n", arr);
    printf("%p\n", &arr);
    return 0;
}

arr 和 &arr 有什么區(qū)別呢?

其運行結(jié)果如下:

在這里插入圖片描述

如果你認(rèn)為它們代表的含義是正確的,不妨試著運行下面這個代碼

#include <stdio.h>
int main()
{
	int arr[5] = { 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;
}

我的編譯器下運行結(jié)果如下

在這里插入圖片描述

如果 arr 和 &arr 代表的含義一樣,那么后面兩個的結(jié)果應(yīng)該也是一致的,但是卻不一樣。

實際上: &arr 表示的是整個數(shù)組的地址,而不是數(shù)組首元素的地址。

數(shù)組的地址+1,跳過整個數(shù)組的大小,所以 &arr+1 相對于 &arr 的差值是40

在這里插入圖片描述

在這里插入圖片描述

3.3數(shù)組指針

數(shù)組指針就是一個指向數(shù)組的指針,意味著,這個指針內(nèi)存放的是數(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; 
}

我們來使用下指向一維數(shù)組的數(shù)組指針

//使用函數(shù)打印數(shù)組內(nèi)的內(nèi)容
# include <stdio.h>
void print_arr(int(*p)[10], int sz) //傳過來的是數(shù)組的地址,用指針來接收
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", (*p)[i]); //先解引用找到數(shù)組
	}
}
int main(void)
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
	int sz = sizeof(arr) / sizeof(arr[0]); //求出數(shù)組的元素個數(shù)
	print_arr(&arr, sz);
	return 0;
}

4.數(shù)組傳參和指針傳參

在寫代碼的過程中,為了更好地利用模塊化的特點,我們會使用大量的函數(shù)。但是在將一個功能封裝成函數(shù)的過程中,我們就不可避免的會傳過去數(shù)組和指針,那么函數(shù)是如何接受的呢?

4.1一維數(shù)組傳參

以下是常見的一維數(shù)組傳參

#include <stdio.h>
void test(int arr[]) //直接用數(shù)組接收,空間大小可以省略
{}
void test(int arr[10]) //直接用數(shù)組接收,空間大小可以指明
{}
void test(int *arr) //接收數(shù)組首元素的地址
{}
void test2(int *arr[20]) //直接用數(shù)組接收
{}
void test2(int **arr) //傳過來一級指針的地址,使用二級指針接收
{}
int main()
{
 int arr[10] = {0};
 int *arr2[20] = {0}; //存放了20個int*的數(shù)組
 test(arr); //傳過去的是首元素的地址
 test2(arr2);
}

4.2二維數(shù)組傳參

當(dāng)我們在談?wù)摱S數(shù)組首元素的時候指的是第一行!
數(shù)組名是首元素的地址,在二維數(shù)組中指的是第一行的地址

void test(int arr[3][5])//直接用二維數(shù)組接收
{}
void test(int arr[][])//錯誤的接收!列不能省略
{}
void test(int arr[][5])//行是可以省略的,但是列一定不能省略
{}
//總結(jié):二維數(shù)組傳參,函數(shù)形參的設(shè)計只能省略第一個[]的數(shù)字。
//因為對一個二維數(shù)組,可以不知道有多少行,但是必須知道一行多少元素。
//這樣才方便運算。
void test(int *arr)//錯誤接收!傳過來的是第一行一維數(shù)組的地址
{}
void test(int* arr[5])//錯誤接收!這是一個存放int*類型的數(shù)組,而數(shù)組內(nèi)的元素是int
{}

//由于二維數(shù)組的首元素是第一行,每一行是一個一維數(shù)組
//因此可以寫成指向一維數(shù)組的指針
void test(int (*arr)[5])
{}
void test(int **arr) //錯誤!
{}
int main()
{
 int arr[3][5] = {0};
 test(arr);
}

4.3一級指針傳參

#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; }

4.4二級指針傳參

#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;
}

5.函數(shù)指針

在之前的學(xué)習(xí)當(dāng)中不會每天使用函數(shù)指針,但是請不要忘記它的存在。
什么是函數(shù)指針?顧名思義,函數(shù)指針就是指向一個函數(shù)的指針。既然函數(shù)指針是指針,那么它也具有指針的一些特性。比如:在對指針進行間接訪問之前必須要先初始化

//代碼一
int f(int);//f函數(shù)
int (*pf)(int) = &f;

這是函數(shù)初始化的一種方法。

//代碼二
int f(int);
int (*pf)(int) = f;

代碼一和代碼二是等效的。我們用下面一個代碼查看,發(fā)現(xiàn)其打印出來的地址是一樣的。

在這里插入圖片描述

在數(shù)組中,數(shù)組名是數(shù)組首元素的地址。而函數(shù)名則是函數(shù)的首地址。在函數(shù)名使用的時候我們所用的編譯器會將函數(shù)名轉(zhuǎn)化為一個函數(shù)指針,&操作符只是顯示地說明了函數(shù)將隱式執(zhí)行的任務(wù)。

如果你需要將函數(shù)的地址存儲起來,這個時候你就可能會需要用到函數(shù)指針了

void test()
{
	printf("hehe\n");
}
//下面的哪一個語句有能力存放函數(shù)test的地址呢?
void (*pfun1)(); //語句1
void *pfun2(); //語句2

存儲地址應(yīng)該需要用到的是指針

語句1:

pfun1首先和 * 操作符結(jié)合,那么它是一個指針。后面有一個函數(shù)調(diào)用操作符,表明它是一個函數(shù)指針。它所指向的函數(shù)

返回值類型是void

語句2:

pfun2首先和()結(jié)合,那么它是一個函數(shù)。 *和前面的void結(jié)合,表明這個函數(shù)的返回值類型是void*

所以選擇語句1。

6.函數(shù)指針數(shù)組

我們知道數(shù)組是存儲一組相同類型的數(shù)據(jù),在此之前我們再來回顧一下指針數(shù)組

int *arr[10];
//數(shù)組的每個元素是int*

這是一個數(shù)組,數(shù)組存放了10個int*類型的數(shù)據(jù)。

按照這個思路,我們把很多函數(shù)的地址存放在數(shù)組中,那么它就是一個函數(shù)指針數(shù)組。

下面我們一起來實現(xiàn)它

首先它是一個數(shù)組 [ ], 存放的數(shù)據(jù)類型為函數(shù)指針,int (*)()類型的是函數(shù)指針

int (*parr1[10])();
int *parr2[10]();
int (*)() parr3[10];

7.指向函數(shù)指針數(shù)組的指針

經(jīng)過我們上面這么多的推導(dǎo),這個也就很容易就能表示出來

指向函數(shù)指針數(shù)組的指針是一個 指針, 指針指向一個 數(shù)組 ,數(shù)組的元素都是 函數(shù)指針

void test(const char* str)
{
 printf("%s\n", str);
}
int main()
{
 //函數(shù)指針pfun
 void (*pfun)(const char*) = test;
 //函數(shù)指針的數(shù)組pfunArr
 void (*pfunArr[5])(const char* str);
 pfunArr[0] = test;
 //指向函數(shù)指針數(shù)組pfunArr的指針ppfunArr
 void (*(*ppfunArr)[10])(const char*) = &pfunArr;
 return 0;
}

8.回調(diào)函數(shù)

回調(diào)函數(shù):回調(diào)函數(shù)就是將一個函數(shù)的函數(shù)指針作為參數(shù)傳遞給另一個函數(shù),而這個函數(shù)就是回調(diào)函數(shù)。

回調(diào)函數(shù)不是由該函數(shù)的實現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時由另外的一方調(diào)用的,用于對該事件或條件進行響應(yīng)。

庫函數(shù)中的qsort函數(shù)就是一個典型的回調(diào)函數(shù)

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • C語言實現(xiàn)搶紅包程序代碼精簡版

    C語言實現(xiàn)搶紅包程序代碼精簡版

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)搶紅包程序代碼的精簡版,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • C++日歷拼圖的解法你了解嗎

    C++日歷拼圖的解法你了解嗎

    這篇文章主要為大家詳細介紹了日歷拼圖C++的解法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • C語言數(shù)據(jù)結(jié)構(gòu)樹的雙親表示法實例詳解

    C語言數(shù)據(jù)結(jié)構(gòu)樹的雙親表示法實例詳解

    這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)樹的雙親表示法實例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • C++使用鏈表存儲實現(xiàn)通訊錄功能管理

    C++使用鏈表存儲實現(xiàn)通訊錄功能管理

    這篇文章主要為大家詳細介紹了C++使用鏈表存儲實現(xiàn)通訊錄功能管理,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C++模擬實現(xiàn)vector流程詳解

    C++模擬實現(xiàn)vector流程詳解

    這篇文章主要介紹了C++容器Vector的模擬實現(xiàn),Vector是一個能夠存放任意類型的動態(tài)數(shù)組,有點類似數(shù)組,是一個連續(xù)地址空間,下文更多詳細內(nèi)容的介紹,需要的小伙伴可以參考一下
    2022-08-08
  • C++實現(xiàn)一個簡單消息隊列的示例詳解

    C++實現(xiàn)一個簡單消息隊列的示例詳解

    消息隊列在多線程的場景有時會用到,尤其是線程通信跨線程調(diào)用的時候,就可以使用消息隊列進行通信。本文將利用C++實現(xiàn)一個簡單的消息隊列,感興趣的可以了解一下
    2022-12-12
  • visual studio 建立dll類型工程、控制臺程序

    visual studio 建立dll類型工程、控制臺程序

    這篇文章主要介紹了visual studio 建立dll、控制臺類型工程的相關(guān)知識,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧
    2018-05-05
  • 手把手教你實現(xiàn)一個C++單鏈表

    手把手教你實現(xiàn)一個C++單鏈表

    鏈表是一種數(shù)據(jù)結(jié)構(gòu),用于數(shù)據(jù)的存儲。這篇文章主要為大家介紹了如何實現(xiàn)一個C++單鏈表,文中的示例代碼講解詳細,感興趣的小伙伴可以嘗試一下
    2022-11-11
  • json error: Use of overloaded operator [] is ambiguous錯誤的解決方法

    json error: Use of overloaded operator [] is ambiguous錯誤的解決方

    今天小編就為大家分享一篇關(guān)于json error: Use of overloaded operator [] is ambiguous錯誤的解決方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • 深入淺析OpenCV?copyTo()函數(shù)

    深入淺析OpenCV?copyTo()函數(shù)

    在Mat矩陣類的成員函數(shù)中copyTo(roi , mask)函數(shù)是非常有用的一個函數(shù),尤其是后面的mask可以實現(xiàn)蒙版的功能,下面通過本文給大家介紹下OpenCV copyTo()函數(shù)的相關(guān)知識,感興趣的朋友一起看看吧
    2022-01-01

最新評論