![](/img/trans.png)
[英]What's the difference between Single pointer and Double pointers for array of strings
[英]What is the difference between double pointers and single pointer in C functions
我是 C 編程的新手,開始處理指針並將內存分配給對象。 我想制作一個簡單的程序,它可以從用戶那里讀入 (x) 個元素,然后使用函數簡單地將它們打印出來。
這是我一開始的初始代碼。 該代碼正在正確讀取用戶輸入,但它給出了錯誤的輸出並在主函數中顯示元素時崩潰。
int main() {
int *myArr;
int myArrSize;
getInputArr(&myArrSize, &myArr);
for (int i = 0; i < myArrSize; i++) {
printf("Element No.%i: %i\n", i, myArr[i]);
}
free(myArr);
return 0;
}
void getInputArr(int *arrSize, int *arr) {
printf("Please Enter Length of Array: \n");
scanf("%i", arrSize);
arr = (int *) malloc(*arrSize * sizeof(int));
printf("Enter %i Numbers!\n", *arrSize);
for (int i = 0; i < *arrSize; i++) {
scanf("%i", &arr[i]);
}
}
搞砸之后,我終於使用雙指針讓它工作了,但我不確定它是如何完全工作的,有人可以解釋為什么下面的代碼表現得像預期的那樣嗎?
int main() {
int *myArr;
int myArrSize;
getInputArr(&myArrSize, &myArr);
for (int i = 0; i < myArrSize; i++) {
printf("Element No.%i: %i\n", i, myArr[i]);
}
free(myArr);
return 0;
}
void getInputArr(int *arrSize, int **myArr) {
printf("Please Enter Length of Array: \n");
scanf("%i", arrSize);
*myArr = (int *) malloc(*arrSize * sizeof(int));
printf("Enter %i Numbers!\n", *arrSize);
for (int i = 0; i < *arrSize; i++) {
scanf("%i", &((*myArr)[i]));
}
}
在您的實現中有一些令人驚訝的事情,但最終它們都有意義,實際上它們必須存在才能使此實現工作。
int *myArr
在main
中模擬一個int
數組,但在getInputArr
您使用“雙指針” int **myArr
來引用它。 但這是有道理的,因為任何時候你想從一個像這樣“通過引用”的函數返回一些東西,你需要使用一個指針——一個額外的指針。 要通過引用返回 int,您可以使用int *
。 但是要通過引用返回int *
,您需要一個int **
。 您(正確)在main
中調用getInputArr(&myArrSize, &myArr)
的事實表明getInputArr
的第二個參數將是int **
。scanf
,您傳遞給scanf
的參數旁邊沒有&
以供%d
讀入。 這是非常不尋常的,但在這種情況下它是絕對正確的,因為arrSize
已經是一個指針。*myArr = (int *) malloc(*arrSize * sizeof(int))
。 這是我在您最初的(非工作)實現中發現的第一件事,這是非常錯誤的。 在getInputArr
, myArr
是指向要設置的指針的指針。 所以*myArr
是您要設置的指針。scanf("%i", &((*myArr)[i]));
. 這看起來很丑陋,可能有更簡單的方法來編寫它,但它是正確的。 讓我們分解一下。 同樣, myArr
是指向您要使用的指針的指針。 所以*myArr
是您要使用的指針。 所以(*myArr)[i]
是您想要使用的模擬數組(由指針指向)的一個元素。 您需要顯式括號,因為如果您編寫*myArr[i]
這將意味着,“獲取myArr
指向的第i
個元素,將其解釋為指針,然后獲取內容。” 但是你想(和,用括號,你有)什么是“取myArr
,把它解釋為指針,把東西它指向的,這是*myArr
和解釋,作為一個指針,最后拿i
'它(第二個指針)指向的第一個元素。”您有多個級別的指針使您感到困惑。 但是,如果您正在處理的動態分配的數組存在於結構中呢? 然后我們只需要處理該結構上的指針傳遞(“引用”)語義。
考慮以下。 請參閱注釋以獲取解釋。
/* Basic stuff. */
#include <stdio.h>
#include <stdlib.h>
/* Here's our struct.
* It contains the size of the array,
* and the pointer to the memory allocated for the array.
*/
typedef struct dyn_int_array {
size_t size;
int * array;
} dyn_int_array_t;
/* Forward declarations for a function which creates and
* returns our dynamic_int_array struct.
*/
dyn_int_array_t * create_dyn_int_array();
/* ... and here's where you see that we don't want to
* pass the struct by value, but rather effectively by
* reference by passing a pointer to it.
*/
void scan_into_dyn_int_array(dyn_int_array_t * da);
int main(void) {
dyn_int_array_t * da = create_dyn_int_array();
/* I never bothered to free up the allocated memory,
* because it's not really critical for demonstration here.
*/
}
這些函數的實現如下,但對本演示並不重要,因為您希望看到指針的引用傳遞使用,而不必直接擔心或被兩個級別的指針間接混淆。
dyn_int_array_t * create_dyn_int_array() {
dyn_int_array_t * result = malloc(sizeof(dyn_int_array_t));
fprintf(stdout, "Input an array size: ");
fscanf(stdin, "%zd", &(result->size));
result->array = malloc(sizeof(int) * result->size);
/* Because "da" is already a pointer to dye_int_array_t
* there's no need to get its address.
*/
scan_into_dyn_int_array(result);
return result;
}
void scan_into_dyn_int_array(dyn_int_array_t * da) {
for (int i = 0; i < da->size; i++) {
/* We do have to pass the address of the current
* element of the array to fscanf.
*/
fscanf(stdin, "%d", &(da->array[i]));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.