討論區快速選單
知識庫快速選單
傑米的攝影旅遊筆記 網路投保旅行平安險 政府補助!學嵌入式+物聯網
[ 回上頁 ] [ 討論區發言規則 ]
function 要如何回傳陣列
更改我的閱讀文章字型大小
作者 : msdos(MSDOS)
[ 貼文 45 | 人氣 5090 | 評價 160 | 評價/貼文 3.56 | 送出評價 7 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/4/19 下午 03:00:44
一般的陣列如下
int Add()
{
  int x=0;
  return x;
};

int Add() 改成 int[] Add() 不行呢
1.是因為陣列要先宣告大小嗎?
2.只能用傳址或傳參考的方式回傳陣列嗎?還是有其他的方式.
作者 : flybearcool(flybear) 貼文超過200則人氣指數超過30000點
[ 貼文 283 | 人氣 46547 | 評價 20 | 評價/貼文 0.07 | 送出評價 27 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/4/19 下午 05:00:27

int *b;
b = abc();

int* CTestDlg::abc()
{
    abcd[0] = 3;
    return abcd;
}

我不知道我這樣講對不對,我基礎也不太好,要回傳陣列就是回傳位置吧,所以要回傳一個point…
作者 : shing819(Clier) VC++曠世奇才貼文超過1000則人氣指數超過30000點
[ 貼文 1740 | 人氣 40353 | 評價 8630 | 評價/貼文 4.96 | 送出評價 84 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人msdos註記此篇回應為很有道理 2007/4/19 下午 08:10:59

>一般的陣列如下
>int Add()
>{
> int x=0;
> return x;
>};
>
>int Add() 改成 int[] Add() 不行呢
>1.是因為陣列要先宣告大小嗎?


印象中記得有一種程式語言可以宣告大小,不過忘了.


>2.只能用傳址或傳參考的方式回傳陣列嗎?還是有其他的方式.


傳址或傳參考的方式回傳陣列這比較常用.


不常用範例:
int* Add()
{
static int a[3]={1,2,3};
return a;
}


為何用 static?因為區域變數離開 Block(註),生命周期便結束,
加上 static 後不會離開 Block 就自我了斷.


註:
Block 就是 {}
作者 : sflam(Raymond)討論區板主 Visual C++ .NET卓越專家VC++一代宗師新手入門優秀好手資訊類作業求救頂尖高手C++一代宗師貼文超過4000則
[ 貼文 4945 | 人氣 9172 | 評價 32290 | 評價/貼文 6.53 | 送出評價 142 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人msdos註記此篇回應為最佳解答 2007/4/19 下午 09:16:59
>int *b;
>b = abc();
>
>int* CTestDlg::abc()
>{
> abcd[0] = 3;
> return abcd;
>}
>
>我不知道我這樣講對不對,我基礎也不太好,要回傳陣列就是回傳位置吧,所以要回傳一個point…

如果 'abcd' 是個 local automatic, 那上面這段就錯了. 你不能傳回一個指向 local automatic 的指標, 因為一旦離開該變數所宣告的 block 後 (正式的術語叫 scope), 該變數就不複存在.

致樓主:

只要可以避開傳回 local automatic 的位址的方法都可以用. Clier 大列了一些例子, 這裡給你多些例子:

1. 在函式的上層宣告, 然後傳給函式設值:

  int main(void)
  {
    int a[10];
    ...
    abc(a, sizeof a / sizeof *a);
    ...
  }

  void abc(int a[], const size_t count)
  {
    size_t n;
    for (n = 0; n < count; ++n)
    {
      a[n] = ...;
    }
  }

  這是常用的方法, 但適不適合要看整個程式的設計


2. 陣列在函式內以靜態的型式宣告. 這也是 Clier 所給的例子. 使用這個方法要注意到可能會出現的副作用:

  int* abc(void)
  {
    static int a[] = { 1, 2, 3, 4 };
    return a;
  }

  int main()
  {
    ...
    int *p1 = abc();
    int *p2 = abc();
    ...
  }

 因為 p1, p2 皆指向同一個陣列, 如果你透過 p1 去更改陣列的值, 那透過 p2 來讀取的值是更改後的值. 但從 main() 那裡完全看不出來.


3. 陣列在函式內以動態的型式來配置:

  int* abc(const size_t count )
  {
    int *p = malloc(count * sizeof *p);
    /*
      設 p 內的值
    */
    return p;
  }

 這個方法避開了方法 2 的副作用. 但是要注意到釋放記憶體的問題. 同時如果 abc() 是在另一個 process (比方說 DLL), 那有可能無法跨 process 來釋放記憶體.


4. C 及 C++ 語言都不能直接傳陣列, 函式內所得到的是一個指標, 指向陣列的第一個元素. 如果要傳整個陣列, 唯一的方法就是用 struct 來包:

  #define ARY_SIZE 10
  typedef struct
  {
    int a[ARY_SIZE];
  } MY_STRUCT;

  MY_struct abc(void)
  {
    MY_struct s;
    /*
      設 s.a[n] 的值
    */
    return s;
  }

  int main()
  {
    MY_struct s = abc();
    ...
  }

它會 work 是因為在語法上, struct 類型的變數是當做「一個」物件, 而 pass by value 的傳送方式是複製物件的內容. 所以整個 struct 裡的每一個成員都會被複製.

這個方法的主要缺點是效率. 如果 struct 裡陣列成員有 10000 個元素, 那在傳送的過程中要拷貝 10000 次.


5. 其他的方法大致上都是由這幾種變化而來.

作者 : shing819(Clier) VC++曠世奇才貼文超過1000則人氣指數超過30000點
[ 貼文 1740 | 人氣 40353 | 評價 8630 | 評價/貼文 4.96 | 送出評價 84 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/4/19 下午 10:44:03

>2. 陣列在函式內以靜態的型式宣告. 這也是 Clier 所給的例子. 使用這個方法要注意到可能會出現的副作用:
>
>  int* abc(void)
>  {
>    static int a[] = { 1, 2, 3, 4 };
>    return a;
>  }
>
>  int main()
>  {
>    ...
>    int *p1 = abc();
>    int *p2 = abc();
>    ...
>  }
>
> 因為 p1, p2 皆指向同一個陣列, 如果你透過 p1 去更改陣列的值, 那透過 p2 來讀取的值是更改後的值. 但從 main() 那裡完全看不出來.
>
>

如果改成這樣,陣列就不能被修改,不知道有沒有 side effect?

const int* abc(void)
{
const static int a[] = { 1, 2, 3, 4 };
return a;
}

int main(int argc, char* argv[])
{
const int *nArray = abc();
nArray[1]=8; // don't touch me!
const int *nArray2 = abc();
...
}

作者 : sflam(Raymond)討論區板主 Visual C++ .NET卓越專家VC++一代宗師新手入門優秀好手資訊類作業求救頂尖高手C++一代宗師貼文超過4000則
[ 貼文 4945 | 人氣 9172 | 評價 32290 | 評價/貼文 6.53 | 送出評價 142 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/4/19 下午 11:14:43
>如果改成這樣,陣列就不能被修改,不知道有沒有 side effect?
>
>const int* abc(void)
>{
> const static int a[] = { 1, 2, 3, 4 };
> return a;
>}
>
>int main(int argc, char* argv[])
>{
> const int *nArray = abc();
> nArray[1]=8; // don''t touch me!
> const int *nArray2 = abc();
> ...
>}

沒有 side effect, 但似乎也沒什麼意義 ^^

不如直接把 a[] 在 main() 裡面或外面宣告就可以了
作者 : msdos(MSDOS)
[ 貼文 45 | 人氣 5090 | 評價 160 | 評價/貼文 3.56 | 送出評價 7 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2007/4/20 上午 01:27:24
請教一下 Raymond
例子1.
1.1 使用 const 是怕被修改嗎?
1.2 size_t n 是用處為何?
    執行到這行時為何 n=34359738836 ?

例子2.
#include <iostream.h>

int* abc(void)
{
  static int a[] = { 1, 2, 3, 4 };
  return a;
}

int main()
{
  int *p1 = abc();
  int *p2 = abc();
  int i;

  for(i=0 ; i<4 ; ++i)
  {
   cout<<*(p1+i);
  }
}

以上程式中的 i<4 怎知道有幾個陣列元素
有類似 sizeof a / sizeof *a 這樣的寫法嗎?

例子3.
malloc 函式沒學過,可以舉完整的例子嗎?

例子4.
這樣寫對嗎?一值有錯
#include <iostream.h>
#define ARY_SIZE 10

typedef struct
{
  int a[ARY_SIZE];
} MY_STRUCT;

MY_struct abc(void)
{
  MY_struct s;
  int i;

  for(i=0 ; i<ARY_SIZE ; ++i)
  {
   s.a[i]=i;
  }
 return s;
}

int main()
{
  MY_struct s = abc();
  int i;

  for(i=0 ; i<ARY_SIZE ; ++i)
  {
    cout<<s.a[i];
  }
}
作者 : sflam(Raymond)討論區板主 Visual C++ .NET卓越專家VC++一代宗師新手入門優秀好手資訊類作業求救頂尖高手C++一代宗師貼文超過4000則
[ 貼文 4945 | 人氣 9172 | 評價 32290 | 評價/貼文 6.53 | 送出評價 142 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人msdos註記此篇回應為最佳解答 2007/4/20 上午 02:43:20
>例子1.
>1.1 使用 const 是怕被修改嗎?

'const' 告訴編譯器某個物件是「唯讀」, 幫助你預防一些無心的錯誤, 比方說:

  if (Var = 0) /* 應該是 (Var == 0) */
  {
    ...
  }

如果 Var 是個 const, 那編譯器會產生錯誤訊息.

同時編譯器也可以依此作一些最佳化.

注意: 如果你在後面的程式裡特意的對一個 const 的物件做出修改, 會導致不可預期的結果.


>1.2 size_t n 是用處為何?

它是 sizeof 結果的類型, 是一個正整數, 通常是個 unsigned long.


> 執行到這行時為何 n=34359738836 ?

一個沒有設初始值的自動變數可以是任何值.


>例子2.
>#include <iostream.h>

不是標準頭檔. 標準的頭檔是 <iostream>



>int* abc(void)
>{
> static int a[] = { 1, 2, 3, 4 };
> return a;
>}
>
>int main()
>{
> int *p1 = abc();
> int *p2 = abc();
> int i;
>
> for(i=0 ; i<4 ; ++i)
> {
> cout<<*(p1+i);
> }
>}
>
>以上程式中的 i<4 怎知道有幾個陣列元素

你可以一個一個的去算, 然後把結果放在這裡. 當然, 如果你增減陣列元素的話, 你要一行一行的去檢驗你的程式, 把相關的部份做出更改. 這是一個很累的做法.


可以用一個全域的 const 整數來設陣列的大小:

  const int ARY_SIZE = 10;
  ...
  int a[ARY_SIZE] = { 1, 2, 3, 4 };
  ...
  for (i = 0; i < ARY_SIZE; ++i)
  {
    ...
  }

這個方法當然也不錯, 尤其是在陣列大小超出初始值數目的情況下, 後面的元素自動設為 0.

另外就是用 (sizeof a / sizeof *a) 來自動幫你計算有幾個元素.

注意: 這個寫法只能用在陣列. 一旦陣列傳入函式, 陣列就降格為指標, 就不能用這個方法.

>有類似 sizeof a / sizeof *a 這樣的寫法嗎?

不明白你是什麼意思 @@


>例子3.
>malloc 函式沒學過,可以舉完整的例子嗎?

上面的例子就差不多完整了, 只是少個 free() 而已. 如果你是用 C++, 那應該用 new 或 new[].


>例子4.
>這樣寫對嗎?一值有錯

「一值」是那個「值」? ^^


>#include <iostream.h>

#include <iostream>

>#define ARY_SIZE 10

用 C++ 嗎? 用 const 變數比較好:

  const int ARY_SIZE = 10;


>typedef struct
>{
> int a[ARY_SIZE];
>} MY_STRUCT;
>
>MY_struct abc(void)

注意 MY_struct 的大小寫.


>{
> MY_struct s;

注意 MY_struct 的大小寫.

〔這是本討論區的問題, 它會將一些看起來像是 C 關鍵字的 substring 變成小寫.〕

> int i;
>
> for(i=0 ; i<ARY_SIZE ; ++i)

用 C++? int i 可以在 for() 裡面宣告:

  for(int i = 0; i < ARY_SIZE; ++i)


> {
> s.a[i]=i;
> }
> return s;
>}
>
>int main()
>{

〔..略..〕

main() 裡面的問題同上.

>}

 板主 : 青衫 , Raymond
 > Visual C++ - 討論區
 - 最近熱門問答精華集
 - 全部歷史問答精華集
 - Visual C++ - 知識庫
  ■ 全站最新Post列表
  ■ 我的文章收藏
  ■ 我最愛的作者
  ■ 全站文章收藏排行榜
  ■ 全站最愛作者排行榜
  ■  月熱門主題
  ■  季熱門主題
  ■  熱門主題Top 20
  ■  本區Post排行榜
  ■  本區評價排行榜
  ■  全站專家名人榜
  ■  全站Post排行榜
  ■  全站評價排行榜
  ■  全站人氣排行榜
 請輸入關鍵字 
  開始搜尋
 
Top 10
評價排行
Visual C++
1 青衫 11070 
2 Raymond 10090 
3 Clier 7630 
4 小約翰 2500 
5 Cog 2030 
6 coco 1870 
7 aming 1410 
8 牧童哥 1400 
9 r2109 1380 
10 Akira 1350 
Visual C++
  專家等級 評價  
  一代宗師 10000  
  曠世奇才 5000  
  頂尖高手 3000  
  卓越專家 1500  
  優秀好手 750  
Microsoft Internet Explorer 6.0. Screen 1024x768 pixel. High Color (16 bit).
2000-2019 程式設計俱樂部 http://www.programmer-club.com.tw/
0.15625