討論區快速選單
知識庫快速選單
沒有人比Cloudera更了解大數據 傑米的攝影旅遊筆記
[ 回上頁 ] [ 討論區發言規則 ]
C語言 函數 陣列參數 傳址?傳值?呼叫
更改我的閱讀文章字型大小
作者 : redonizuka(Saul)
[ 貼文 12 | 人氣 0 | 評價 0 | 評價/貼文 0 | 送出評價 4 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2015/3/2 上午 10:48:52
請問一下,在C語言裡面,一個陣列被當成函數參數呼叫的時候,

陣列參數會是以傳址呼叫的方式,如同指標,跟基本資料型態的傳值呼叫不同

但若我有一個程式內 我有很多個函數

但都使用同一個陣列,此陣列我並不想因為某函數呼叫他進行運算後改變

我該如何在程式上做修改

example:
#include <stdio.h>
#include <stdlib.h>


void a(int array[],int i);
void b(int array[],int i);

int main()
{
     int qu[10]={1,2,3,4,5,6,7,8,9,10};
     a(qu,3);
     printf("\n");
     b(qu,4);
     return 0;
}


void a(int qu[],int i)
{
     int b=0;
     qu[i]=100;
     for(b;b<10;b++)
     printf("%d ",qu[b]);
}

void b(int qu[],int i)
{
     int b=0;
     qu[i]=200;
     for(b;b<10;b++)
     printf("%d ",qu[b]);
}

上面答案會是
1 2 3 100 5 6 7 8 9 10
1 2 3 100 200 6 7 8 9 10

但我想要的是
1 2 3 100 5 6 7 8 9 10
1 2 3 4 200 6 7 8 9 10



如何把函數 陣列參數從傳址呼叫改成傳值呼叫?
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 343 | 人氣 0 | 評價 1650 | 評價/貼文 4.81 | 送出評價 16 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人redonizuka註記此篇回應為最佳解答 2015/3/2 上午 11:51:21
> 陣列參數會是以傳址呼叫的方式,如同指標,跟基本資料型態的傳值呼叫不同
C 函式的參數只有一種傳遞方式,就是傳值傳遞,包括陣列。

> 但若我有一個程式內 我有很多個函數
> 但都使用同一個陣列,此陣列我並不想因為某函數呼叫他進行運算後改變
> 我該如何在程式上做修改
如果你不希望函式修改參數的內容,請加上 const 修飾字,如:
void a(const int array[],int i);
接下來:
1. 如果函式只是查詢陣列的內容,可以不要管他。
2. 如果函式需要修改陣列內容,又不希望影響這個傳入陣列的內容。那你應該在函式裡另外複製一份函式自己用的陣列,然後使用他。
作者 : ozzy123(ozzy) 資訊類作業求救卓越專家C++卓越專家貼文超過4000則人氣指數超過30000點
[ 貼文 4464 | 人氣 37262 | 評價 10860 | 評價/貼文 2.43 | 送出評價 49 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2015/3/2 下午 12:19:23
int main()
{
     int qu[10]={1,2,3,4,5,6,7,8,9,10};
     a(qu,3); // this must be modified
     /* it should be following=
     for ( int i = 0 ; i < 10 ; i ++ )
     a(qu[i],3) ;
     */
     printf("\n");
     /* it should be following=
     for ( int i = 0 ; i < 10 ; i ++ )
     a(qu[i],4) ;
     */
     return 0;
}


void a(int qu,int i)
{
     int b=0;
     q[10] ={0};

     for(b;b<10;b++)
     printf("%d ",q[b]) ;

}

void b(int qu,int i)
{
     int b=0;
     qq[10]={0};
     qq[i] = 200 ;

     for(b;b<10;b++)
     printf("%d ",qq[b]);
}
作者 : sflam(Raymond)討論區板主 Visual C++ .NET卓越專家VC++一代宗師新手入門優秀好手資訊類作業求救頂尖高手C++一代宗師貼文超過4000則
[ 貼文 4945 | 人氣 9172 | 評價 32290 | 評價/貼文 6.53 | 送出評價 142 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人redonizuka註記此篇回應為很有道理 2015/3/2 下午 09:33:06
>請問一下,在C語言裡面,一個陣列被當成函數參數呼叫的時候,
>陣列參數會是以傳址呼叫的方式,如同指標,跟基本資料型態的傳值呼叫不同

如二樓「燃燒」大大所言, 在 C 語言裡, 參數的傳遞都是值.

除了用在 sizeof() 運算子外, 在任何其它的式子裡, 陣列的名字實際上是一個位址, 它第一個元素的位址:
  array ==> &array[0].

當你把陣列名字 array 當作函式參數時, 編譯器會把它轉成 &array[0], 所以它傳入的是位址這個「值」. 在進入函式後, 函式得到的就是一個指標, 指向你 main() 裡定義的陣列.

在函式的宣告裡, 參數的宣告可以寫成 int a[] 或 int a*, 它們都是同樣的意思.


>但若我有一個程式內 我有很多個函數
>但都使用同一個陣列,此陣列我並不想因為某函數呼叫他進行運算後改變

也就是說, 你要在函式裡複製指標所指向的陣列, 然後針對複製的陣列做運算. 至少有兩個方法:
1. 在你函式裡手動複製陣列, 然後針對複製的陣列做運算.

2. 把陣列用 struct 來包, 然後傳入 struct. 因為「傳值」的關係, 所以編譯器必須複製整個 struct 物件. 在 C 語言哩, 複製 struct 物件的定義是複製 struct 內的它所有成員, 所以如果你用 struct 來包陣列, 整個陣列都會被複製:

    typedef struct MyStruct
    {
     int array[10];
    } MyStruct;

    void func(MyStruct s)
    {
     int n;
     for (n = 0; n < sizeof(s.array); ++n)
     {
     s.array[n] *= 2;
     }
    }

    int main()
    {
     MyStruct qu = { {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} };
     func(qu);
    }

用 struct 來包是最方便的方法, 因為編譯器會自動生產適當的程式碼來做複製的動作. 但複製是花時間的, 如果 struct 裡面的成員很多或陣列很大, 不必要的複製會降低執行效率.

作者 : redonizuka(Saul)
[ 貼文 12 | 人氣 0 | 評價 0 | 評價/貼文 0 | 送出評價 4 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2015/3/4 上午 09:46:00
感謝大家!!

以了解其中原理,以及我已應用於我所做的練習上了,很有幫助(Y)
 板主 : Jammy
 > 新手入門 - 討論區
 - 最近熱門問答精華集
 - 全部歷史問答精華集
 - 新手入門 - 知識庫
  ■ 全站最新Post列表
  ■ 我的文章收藏
  ■ 我最愛的作者
  ■ 全站文章收藏排行榜
  ■ 全站最愛作者排行榜
  ■  月熱門主題
  ■  季熱門主題
  ■  熱門主題Top 20
  ■  本區Post排行榜
  ■  本區評價排行榜
  ■  全站專家名人榜
  ■  全站Post排行榜
  ■  全站評價排行榜
  ■  全站人氣排行榜
 請輸入關鍵字 
  開始搜尋
 
Top 10
評價排行
新手入門
1 Raymond 900 
2 BK. 820 
3 Jasper 500 
4 太子 500 
5 Benson 410 
6 joe 400 
7 DEMO999 370 
8 青衫 300 
9 小朱 300 
10 Eric Ho 290 
新手入門
  專家等級 評價  
  一代宗師 10000  
  曠世奇才 5000  
  頂尖高手 3000  
  卓越專家 1500  
  優秀好手 750  
Microsoft Internet Explorer 6.0. Screen 1024x768 pixel. High Color (16 bit).
2000-2018 程式設計俱樂部 http://www.programmer-club.com.tw/
0.046875