個人主頁:PingdiGuo_guo
收錄專欄:C++干貨專欄
文章目錄
前言
1.字符指針
1.1字符指針的概念
1.2字符指針的用處
1.3字符指針的操作
1.3.1定義
1.3.2初始化
1.4字符指針使用注意事項
2.數組參數,指針參數
2.1數組參數
2.1.1數組參數的概念
2.1.2數組參數的作用
2.1.3一維數組的傳參
2.1.4二維數組的傳參
2.2指針參數
2.2.1指針參數的概念
2.2.2指針參數的作用
2.2.3一級指針與二級指針
2.2.3一級指針的傳參
2.2.4二級指針的傳參
2.3練習
2.3.1數組參數的練習題目
2.3.2指針參數的練習題目
總結
前言
相關文章:C++指針(二)、C++指針(一)
本篇博客是介紹字符指針,數組參數與指針參數的。
點贊破五十,更新下一期。
1.字符指針
1.1字符指針的概念
字符指針是指向字符數組或字符串的指針。在C語言中,字符數組和字符串都是以字符指針的形式來操作和訪問的。字符指針指向字符數組或字符串的第一個字符的地址,通過指針可以訪問數組或字符串中的各個字符。
1.2字符指針的用處
字符指針有很多用途,以下是一些常見的用途:
1. C字符串操作:字符指針可以用來處理C字符串,包括字符串的拷貝、連接、比較等操作。由于C字符串以null字符結尾,我們可以使用字符指針來訪問和操作字符串的每個字符。
2. 字符串數組訪問:字符指針可以用于訪問字符串數組中的每個字符串。通過遞增指針的方式,可以依次訪問字符串數組中的每個元素。
3. 動態內存分配:字符指針可以用于動態分配內存,即在程序運行時根據需要分配內存空間。通過使用`new`運算符,可以分配一段連續的內存,并返回第一個元素的指針。
4. 字符指針數組:字符指針可以用于創建指向字符的指針數組。這在處理多個字符串時非常有用,每個指針可以指向一個獨立的字符串。
5. 文件操作:字符指針可以用于進行文件的讀取和寫入操作。通過指針的方式,我們可以逐字符或逐行讀取文件內容,并將指針移動到文件的特定位置。
這些只是字符指針的一些常見用途,實際上,字符指針在C和C++中有廣泛的應用,可以用于字符串處理、動態內存管理、文件操作等多種場景。
1.3字符指針的操作
1.3.1定義
字符指針需要關鍵字char*來定義,其他部分與普通指針的定義相同。如下:
char* ptr;
這樣,我們就定義了一個字符指針。
1.3.2初始化
字符指針初始化有兩種方式:
1.定義一個字符并為其賦值,然后用&來獲取這個字符變量的地址。代碼如下:
#include <bits/stdc++.h>
using namespace std;
int main()
{char ch = 'w';char* pc = &ch;cout<<*pc<<endl;return 0;
}
到這里,可能有些同學會疑惑:*pc里不是存儲了變量ch的地址了么,為啥輸出的是ch里的值呢?
這里我們要注意,在代碼中,
*pc
是一個解引用操作符,它用于獲取指針pc
所指向的內存地址上存儲的值。在這種情況下,*pc
表示獲取指針pc
所指向的內存地址上存儲的字符。所以,cout<<*pc
輸出的是ch
里的值,即字符w
。
那可能有些同學又要問了:PingdiGuo_guo,那啥情況輸出的是地址呢?
注意:當我們直接輸出指針變量本身時,會輸出該指針變量所存儲的地址而不是地址上的值。如果要輸出指針變量所指向的地址上的值,需要使用解引用操作符*。
以下是一個例子:
#include <iostream>
using namespace std;int main() {int x = 10;int* ptr = &x;cout << ptr << endl; ? // 輸出指針變量ptr的值,即x的地址cout << *ptr << endl; ?// 輸出指針ptr所指向的地址上存儲的值,即x的值return 0;
}
上述代碼輸出結果:
第一行輸出的是指針變量ptr存儲的地址,第二行輸出的是指針ptr所指向的地址上存儲的值。
2.我們直接把一個字符串賦值給指針變量。如下:
?#include <iostream>
using namespace std;
int main()
{const char* ps = "hello.";cout<<ps<<endl;return 0;
}?
大家看一看,運行上述代碼,*ps里儲存的是什么呢?
有同學覺得儲存的的應該是字符串"hello."的地址,實際上儲存的是字符串"hello."的首字符,也就是字符'h'的地址。
1.4字符指針使用注意事項
字符指針使用注意事項:
1. 注意字符串的結束符:C語言中的字符串以'\0'作為結束符,因此在使用字符指針操作字符串時,需要確保字符串末尾有一個'\0'字符,否則可能導致未定義的行為。
2. 避免修改字符串常量:字符串常量是只讀的,因此嘗試修改字符串常量的內容會導致編譯錯誤或者運行時錯誤。如果需要修改字符串,應該使用可修改的字符數組或者動態分配內存的字符指針。
3. 空指針檢查:在使用字符指針之前,應該進行空指針檢查,以避免對空指針進行操作,導致程序崩潰或者出現未定義的行為。
4. 確保指針指向有效的內存區域:在使用字符指針操作字符串時,應確保指針指向的內存區域包含了足夠的空間,以存儲字符串的內容,并且字符串的結束符'\0'也需要在指針指向的內存區域內。
5. 避免指針越界訪問:在使用字符指針操作字符串時,應避免指針越界訪問,即超過了字符串的有效范圍進行訪問,這可能導致程序崩潰或者出現未定義的行為。
6. 避免指針懸掛:在使用字符指針時,需要確保指針指向的內存區域有效,并且在指針不再使用時及時釋放或者置為NULL,以避免產生懸掛指針或者內存泄漏的問題。
7. 注意指針運算的規則:字符指針支持指針運算,例如指針加法和指針減法,但要注意指針運算時遵循指針的類型大小,以避免指針運算越界或者計算錯誤。
8. 使用函數庫提供的字符串操作函數:C語言提供了一系列函數庫來操作字符串,例如strcpy、strlen、strcat等,使用這些函數能夠更方便、安全地操作字符串,同時避免常見的錯誤。
2.數組參數,指針參數
2.1數組參數
2.1.1數組參數的概念
數組參數是指在函數的參數列表中聲明一個數組作為參數。當函數被調用時,實際傳遞給該參數的是數組的地址,而不是整個數組本身。通過使用數組參數,可以將數組的內容傳遞給函數,并在函數中對數組進行操作或者返回相應的結果。
2.1.2數組參數的作用
數組參數在函數中的作用主要包括以下幾點:
1. 傳遞數組數據:通過數組參數,可以將數組的數據傳遞給函數進行處理。函數可以讀取、修改數組的元素,執行各種操作。
2. 減少內存開銷:使用數組參數可以避免將整個數組的副本傳遞給函數,而是只傳遞數組的地址或首元素地址。這樣可以減少內存開銷和數據復制次數。
3. 返回數組數據:函數也可以通過數組參數返回數據。在函數內部修改數組元素后,函數外部的數組也會被修改。
4. 可變長度數組:在函數參數中使用可變長度數組,可以根據需要傳遞不同大小的數組。這樣可以編寫更加靈活的函數,適應不同規模的數據。
5. 簡化代碼:通過使用數組參數,可以將對數組的一系列操作封裝在函數中,提高代碼的可讀性和可維護性。
總的來說,數組參數可以使函數更加靈活、高效地處理數組數據,提高代碼的可復用性和可維護性。它是C語言中非常重要的函數參數類型之一。
2.1.3一維數組的傳參
void is(int a[])
{
}
void id(int a[100])
{
}
void ih(int* a[10])
{
}
?
void ij(int* a)
{
}?
void ig(int** a)
{
}
注:上述這些格式都可以運行。
2.1.4二維數組的傳參
二維數組的傳參基本形式與一維數組類似,只是在聲明參數時需要指明數組的行數和列數。
// 形參為二維數組,指定列數的方式
void functionName(dataType arrayName[][columns], int rows) {// 函數體// 可以通過雙重循環訪問和修改數組元素
}
// 形參為二維數組,指定指針的方式
void functionName(dataType *arrayName[], int rows, int columns) {// 函數體// 可以通過雙重循環訪問和修改數組元素
}
// 形參為二維數組,指定指向指針的指針的方式
void functionName(dataType **arrayName, int rows, int columns) {// 函數體// 可以通過雙重循環訪問和修改數組元素
}
在上述代碼中,dataType是數組中元素的數據類型,arrayName是二維數組的名稱,rows是數組的行數,columns是數組的列數。
在函數參數列表中,我們可以使用dataType arrayName[][columns]或者dataType *arrayName[]或dataType **arrayName來聲明一個二維數組作為參數。
在函數體內部,可以使用雙重循環來訪問和修改二維數組的元素。
2.2指針參數
2.2.1指針參數的概念
指針參數是指函數中的參數被聲明為指針類型的參數。指針參數允許函數通過引用傳遞內存地址,從而能夠修改原始數據的值。
2.2.2指針參數的作用
指針參數的作用有以下幾個方面:
1. 傳遞大型數據結構:通過將指針作為參數傳遞給函數,可以避免復制整個數據結構。這對于大型結構體或數組來說尤為重要,可以提高程序性能。
2. 在函數內部修改變量的值:通過傳遞指向變量的指針作為參數,函數可以直接修改變量的值。這對于需要在函數中修改全局變量或者需要通過函數返回多個值的情況非常有用。
3. 動態內存分配:通過指針參數,可以在函數內部對動態分配的內存進行操作。例如,在函數中動態創建一個數組,并通過指針參數返回數組的地址。
4. 傳遞數組:通過將數組的首地址作為指針參數傳遞給函數,可以在函數內部操作數組中的元素。
需要注意的是,使用指針參數需要謹慎,避免出現空指針或者越界訪問等問題。在使用指針參數時,需要確保傳遞正確的地址,并在函數內部對指針進行適當的處理和保護。
總之,指針參數在函數傳參中具有重要作用,可以通過引用傳遞內存地址,實現對變量和數據的修改和操作。
2.2.3一級指針與二級指針
一級指針和二級指針是指針的不同級別。
一級指針(Level 1 Pointer)是指一個指針變量(如int*)指向一個存儲地址,該地址保存了一個值或者另一個指針。通過一級指針可以直接訪問到被指向的內存地址中的值。
二級指針(Level 2 Pointer),也被稱為指向指針的指針,是指一個指針變量(如int**)存儲了一個指針的地址。通過二級指針可以間接地訪問到被指向的內存地址中的值。
二級指針常用于需要對一級指針進行修改的情況,例如在函數中傳入一個指針的指針,以便修改指針的值。同時,你也可以定義三級指針、四級指針以及更高級別的指針,但在實際開發中很少用到。
2.2.3一級指針的傳參
一級指針的傳參是通過將指針作為函數的參數傳遞給函數。
在函數中,可以通過一級指針來訪問和修改指針所指向的值。
下面是一級指針傳參的基本形式:
void func(int* ptr) {// 使用指針訪問和修改指針所指向的值*ptr = 10;// ...
}int main() {int x = 0;int* p = &x;// 將指針p作為參數傳遞給函數funcfunc(p);// x的值已經被修改為10return 0;
}
?
在上面的例子中,通過將指針p作為參數傳遞給函數func,函數內部可以通過指針ptr來訪問和修改p所指向的值。在函數中,通過解引用操作符*來訪問指針所指向的值。
需要注意的是,傳遞一級指針作為參數時,函數內部對指針所指向的值的修改是有效的,因為傳遞的是指針變量本身的地址,而不是指針變量的副本。
問:在這種情況下,函數能接受什么參數?
答:在這種情況下,函數func
可以接受一個指向整型變量的指針作為參數。在main
函數中,通過將指針p
作為參數傳遞給func
函數,函數func
可以使用指針訪問和修改指針所指向的值。
2.2.4二級指針的傳參
二級指針的傳參是通過將指向指針的指針作為函數的參數傳遞給函數。
二級指針在某些情況下用于傳遞指針數組或二維數組的地址,或者用于動態分配內存等場景。
下面是二級指針傳參的基本形式:
?
void func(int** ptr) {// 使用二級指針訪問和修改指針所指向的值**ptr = 20;// ...
}int main() {int x = 0;int* p = &x;int** pp = &p;// 將二級指針pp作為參數傳遞給函數funcfunc(pp);// x的值已經被修改為20return 0;
}
在上面的例子中,通過將二級指針pp作為參數傳遞給函數func,函數內部可以通過二級指針ptr來訪問和修改pp所指向的值。在函數中,通過解引用操作符*兩次來訪問指針所指向的值。
需要注意的是,傳遞二級指針作為參數時,需要對指針進行兩次解引用才能訪問到最終的值。在函數內部修改指針所指向的值也是有效的。
此外,還要注意對于二維數組的傳參,可以使用一級指針或二級指針來傳遞二維數組的地址。
問:在這種情況下,函數能接受什么參數?
答:在這種情況下,函數func
可以接受一個指向指向整型變量的一級指針的二級指針作為參數。
2.3練習
2.3.1數組參數的練習題目
題目:
編寫一個函數,接收一個整型數組和數組長度作為參數,并返回數組中的最大值。
步驟:
1. 在main函數中聲明一個整型數組并初始化。
2. 定義一個函數findMax,接收一個整型數組和數組長度作為參數,并返回一個整型值。
3. 在findMax函數中,定義一個變量max,初始化為數組的首個元素。
4. 使用循環遍歷數組,比較數組中的每個元素與max的值,并更新它。
5. 返回最大值。
6. 在main函數中調用findMax函數,并將返回值打印出來。
流程圖:
?
開始
聲明和初始化數組以及定義數組長度
定義函數findMax,接收數組和長度作為參數,并返回最大值
定義變量max,并初始化為數組的首個元素
循環遍歷數組比較當前元素和max的值,若大于max,則更新max的值
返回max
調用findMax函數并打印返回值
結束
?
代碼:
?
#include <iostream>int findMax(int arr[], int size) {int max = arr[0];for (int i = 1; i < size; i++) {if (arr[i] > max) {max = arr[i];}}return max;
}int main() {int arr[] = {3, 5, 1, 4, 2};int size = sizeof(arr) / sizeof(arr[0]);int max = findMax(arr, size);std::cout << "Max: " << max << std::endl;return 0;
}
在這個例子中,findMax函數接收一個整型數組和數組長度作為參數,并返回最大值。函數內部使用循環遍歷數組,比較每個元素與max的值,并根據情況更新它。在main函數中聲明數組arr并初始化,然后調用findMax函數并傳遞相應的參數,將返回值存儲在max變量中,并使用std::cout 打印出來。
運行結果:
2.3.2指針參數的練習題目
題目:
編寫一個函數,接收一個整型數組的指針和數組長度作為參數,并將數組中的所有元素翻轉。
步驟:
1. 在main函數中聲明一個整型數組并初始化。
2. 定義一個函數reverseArray,接收一個指向整型數組的指針和數組長度作為參數,并將數組中的所有元素翻轉。
3. 在reverseArray函數中,使用兩個指針start和end,分別指向數組的起始和末尾位置。
4. 使用循環,交換`start`和`end`指針所指向的元素,并同時將`start`往后移動一位,`end`往前移動一位。
5. 循環繼續,直到start指針超過或等于end指針。
6. 在main函數中調用reverseArray函數,并將修改后的數組打印出來。
流程圖:
?
開始
聲明和初始化數組以及定義數組長度
定義函數reverseArray,接收整型數組指針和長度作為參數
定義指針start,指向數組起始位置
定義指針end,指向數組末尾位置
循環,交換start和end指針所指向的元素,并同時移動start和end指針若start指針超過或等于end指針,則跳出循環
在main函數中調用reverseArray函數,并打印修改后的數組
結束
?
代碼:
?
#include <iostream>void reverseArray(int* arr, int size) {int* start = arr;int* end = arr + size - 1;while (start < end) {int temp = *start;*start = *end;*end = temp;start++;end--;}
}int main() {int arr[] = {1, 2, 3, 4, 5};int size = sizeof(arr) / sizeof(arr[0]);std::cout << "Original array: ";for (int i = 0; i < size; i++) {std::cout << arr[i] << " ";}std::cout << std::endl;reverseArray(arr, size);std::cout << "Reversed array: ";for (int i = 0; i < size; i++) {std::cout << arr[i] << " ";}std::cout << std::endl;return 0;
}
在這個例子中,reverseArray函數接收一個指向整型數組的指針和數組長度作為參數,并將數組中的所有元素翻轉。函數內部使用兩個指針start和end分別指向數組的起始和末尾位置,通過循環交換指針所指向的元素,并同時移動指針,直到start指針超過或等于`end`指針。在main函數中聲明數組arr并初始化,然后調用reverseArray函數并傳遞相應的參數,將數組的元素翻轉。最后使用std::cout打印出原始數組和翻轉后的數組。
運行結果:
總結
本篇博客到這里就結束了,感謝大家的支持與觀看,如果有好的建議歡迎留言,謝謝大家啦!