簡體   English   中英

C函數中雙指針和單指針有什么區別

[英]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]));
    }
}

在您的實現中有一些令人驚訝的事情,但最終它們都有意義,實際上它們必須存在才能使此實現工作。

  1. 您最終希望int *myArrmain中模擬一個int數組,但在getInputArr您使用“雙指針” int **myArr來引用它。 但這是有道理的,因為任何時候你想從一個像這樣“通過引用”的函數返回一些東西,你需要使用一個指針——一個額外的指針。 要通過引用返回 int,您可以使用int * 但是要通過引用返回int * ,您需要一個int ** 您(正確)在main中調用getInputArr(&myArrSize, &myArr)的事實表明getInputArr的第二個參數將是int **
  2. 在 getInputArr 中,當您調用scanf ,您傳遞給scanf的參數旁邊沒有&以供%d讀入。 這是非常不尋常的,但在這種情況下它是絕對正確的,因為arrSize已經是一個指針。
  3. 然后你有*myArr = (int *) malloc(*arrSize * sizeof(int)) 這是我在您最初的(非工作)實現中發現的第一件事,這是非常錯誤的。 getInputArrmyArr是指向要設置的指針的指針。 所以*myArr是您要設置的指針。
  4. 最后,你有一個令人驚嘆的調用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM