2014-12-28 117 views
2

我頭上有一個小小的結。我只是試圖向某人解釋,爲什麼一個小程序按照它的方式使用指針,然後她問我一個不同的方式,這應該(據我所知)工作,但不是。 下面是工作代碼:Scanf - 每參考VS參數參考

#include <stdio.h> 

void inputNums(double *valOne, double *secVal) 
{ 
    printf("Enter your first number: "); 
    scanf("%lf", valOne); 

    printf("Enter your second number: "); 
    scanf("%lf", secVal); 
} 

void sum(double valOne, double secVal) 
{ 
    double result = valOne + secVal; 
    printf("The sum is: %.2f\n", result); 
} 


int main() 
{ 
    double numOne; 
    double numTwo; 

    inputNums(&numOne, &numTwo); 
    sum(numOne, numTwo); 
    return 0; 
} 

下面是不適用的代碼,但我不知道爲什麼:

#include <stdio.h> 

void inputNums(double valOne, double secVal) 
{ 
    printf("Enter your first number: "); 
    scanf("%lf", &valOne); 

    printf("Enter your second number: "); 
    scanf("%lf", &secVal); 
} 

void sum(double valOne, double secVal) 
{ 
    double result = valOne + secVal; 
    printf("The sum is: %.2f\n", result); 
} 


int main() 
{ 
    double numOne; 
    double numTwo; 

    inputNums(numOne, numTwo); 
    sum(numOne, numTwo); 
    return 0; 
} 

我知道這是很簡單的東西,但對於愛上帝,我無法弄清楚。謝謝你們:)

回答

2

有兩個函數調用的代碼將會發生,這需要能夠修改調用者的數據:

  • inputNums(...)的號召,
  • scanf(...)的號召,從內部發生inputNums(...)

爲了的scanf嵌套調用,以便能夠在main修改數據,scanf需要有一個指向main中的數據:這是C函數可以修改其調用者內部局部變量的唯一方法。

在你的第一個例子inputNums有一個指針變量裏面main這樣的修改工作正常,而在第二個例子中它沒有一個指向main變量,因爲按值傳遞的參數。這是打破你的第二個實施。

這裏是正在發生的事情的說明:

Passing by pointer vs. passing by value

在第一種情況下指針numOnemainnumTwo被一路傳遞到scanf,而在第二種情況下scanf看到指針當地valOnesecValinputNums,這是它修改,而不觸及main的變量。

+0

scanf()是一個嵌套函數,還是對inputNums()中的&double進行一個簡單的操作也會打破它呢? – BigBadWolf

+0

@BigBadWolf我添加了一個插圖來顯示正在發生的事情。在'main'內傳遞一個指向變量的指針可以在觸及指針的每個級別上被破壞。爲了使代碼正常工作,最終執行修改的函數(在本例中爲'scanf')必須具有指向要修改的變量的指針。 – dasblinkenlight

1

它很簡單,C中的所有值都默認傳值。

這使得你的inputNums只修改你的變量的副本。

在那比如你的變量是你numOne的地址還有numTwo

這種說法 inputNums(&numOne, &numTwo);

你只發送這將是一些地址numOne和numTwo 的地址副本在你的主棧上。

0

在第二種情況下,inputNums按值取其參數。因此,此處所做的更改不會影響main中的變量。 valOne in inputNumsnumOne的副本。 OTOH,在第一個例子中,因爲inputNums有指針參數,所做的更改是指向他們指向的變量。 valOne,在這種情況下,指向numOnescanf調用修改爲numOne

1

它不起作用,因爲C是傳遞值。在代碼的第二塊,

void inputNums(double valOne, double secVal) 
{ 

值瓦隆和secVal的傳遞中,隨後它們變成局部變量。你的指針代碼正確地改變了這些變量,但是當函數返回時它們仍然被刪除,因爲變量是局部的。

在第一塊,

void inputNums(double *valOne, double *secVal) 
{ 

在傳遞的唯一值是在主方法的範圍兩個變量的地址(即,變量numOne和numTwo);遵循這些指針會導致這些變量,並且當函數返回時,這些變化將保持不變。

+0

好的,謝謝,它的確很簡單。我認爲gcc只是用它們的內容替換void函數,不像nonvoid函數。 – BigBadWolf

1

在第一個例子中,您在做pass-by-reference,而在第二個例子中,它是pass-by-value

在第一個示例中,您將變量numOnenumTwo的地址傳遞給函數inputNums,並且該函數的參數是指針。這意味着這兩個指針valOnesecVal保存着變量的地址numOnenumTwo。因此,修改*valOne*secVal(存儲在兩個指針保存的地址中的值)修改mainnumOnenumTwo)中變量的值。

在第二個例子中,傳遞的numOnenumTwo值到funcion inputNums並且因此,varaibles的副本是由與存儲在numOnenumTwo的初始值被複制到在變量valOnesecVal功能inputNums。修改這些變量不會修改numOnenumTwo的值,因爲所有這些變量都存儲在不同的存儲位置。