2009-01-14 224 views
16

在C++中,數組不能簡單地作爲參數傳遞。在C++中將函數參數作爲函數參數傳遞

void doSomething(char charArray[]) 
{ 
    // if I want the array size 
    int size = sizeof(charArray); 
    // NO GOOD, will always get 4 (as in 4 bytes in the pointer) 
} 

我有沒有辦法知道數組有多大,因爲我只有一個指針數組:如果我創建了一個功能,像這樣的意思。

在不更改方法簽名的情況下,我可以通過哪種方式獲取數組大小並迭代它的數據?


編輯:只是關於解決方案的補充。如果字符數組,具體而言,被初始化像這樣:

char charArray[] = "i am a string"; 

\0已經附加到該陣列的端部。在這種情況下,答案(標記爲接受)可以開箱即用,可以這麼說。

+2

實際上這裏有一個相當大的誤解,你的例子中的語法沒有任何意義:函數在棧上獲取未知數量的數據。忽略你原來的語法,並給函數簽名`void doSomething(char * charArray)`。如果你用char數組[10]; doSomething(array) //c-faq.com/aryptr/aryptrparam.html – kfsone 2013-06-02 17:53:24

回答

22

不改變簽名?追加一個哨兵元素。特別是對於char數組,它可能是用於標準C字符串的空終止'\0'

void doSomething(char charArray[]) 
{ 
    char* p = charArray; 
    for (; *p != '\0'; ++p) 
    { 
     // if '\0' happens to be valid data for your app, 
     // then you can (maybe) use some other value as 
     // sentinel 
    } 
    int arraySize = p - charArray; 

    // now we know the array size, so we can do some thing 
} 

當然,那麼你的數組本身不能包含sentinel元素作爲內容。 對於其他類型(即非char)數組,它可以是任何非法定數據的值。如果不存在這樣的值,則該方法不起作用。

此外,這需要呼叫方的合作。你必須確保調用者保留一組arraySize + 1元素,並且總是設置sentinel元素。

但是,如果您確實無法更改簽名,您的選擇就會受到限制。

+0

代碼示例好嗎?:) – 2009-01-14 21:26:17

+0

是的,我還在打字:) – Reunanen 2009-01-14 21:29:49

+0

非常好的解決方案,像一個魅力工作。謝謝! – 2009-01-14 21:47:36

4

如果它是nullterminated,strlen()將工作。

+1

是的,這是問題中char數組的完美答案,但不適用於其他數據類型。 – Reunanen 2009-01-14 21:35:54

+0

除了寫`doSomething(NULL);`完全合法的事實。 **編譯器**將OP指紋更改爲`char * charArray` :) http://c-faq.com/aryptr/aryptrparam.html – kfsone 2013-06-02 18:01:23

2

單獨從charArray無法確定尺寸。該信息不會自動傳遞給該功能。

當然,如果它是一個空字符結尾的字符串,你可以使用strlen(),但你可能已經考慮過了!

考慮傳遞一個參數或一對指針或一個指針加上一個大小參數的一個參數std::vector<char>

+0

我認爲Yuval對函數簽名的限制。 – Calyth 2009-01-14 21:45:56

+0

@finnw這是因爲它根本不傳遞數組,它只是傳遞一個指針。 – kfsone 2013-06-02 18:00:42

2

這實際上比C++更C,在C++中你可能更願意使用std :: vector。但是,在C中無法知道數組的大小。如果數組是在當前範圍內聲明的,並且僅當它被顯式聲明爲一個大小(編輯:和「與一個大小」,我的意思是它或者聲明爲一個大小整數大小或聲明時初始化,而不是作爲參數傳遞,感謝downvote)。

C中的常見解決方案是傳遞描述數組中元素數量的第二個參數。

編輯:
對不起,錯過了有關不想更改方法簽名的部分。那麼除了別人所描述的解決方案之外,沒有任何解決方案,如果有一些數據在數組中是不允許的,那麼它可以用作終止符(0在C字符串中,-1也是相當常見的,但它取決於您的實際的數據類型,假設字符數組是假設)

1

爲了瞭解在已傳遞給它一個數組的項數的函數,你必須做兩件事情之一:

  1. 傳遞大小參數
  2. 將大小信息以某種方式放入數組中。

你可以做後者在幾個方面:

  • 用NULL或不會在 正常數據出現一些 其他定點終止它。
  • 店的項目中的第一項算,如果數組包含數字
  • 存放指向最後一個條目,如果數組包含指針
35

使用模板。這在技術上不符合你的標準,因爲它改變了簽名,但調用代碼不需要修改。

void doSomething(char charArray[], size_t size) 
{ 
    // do stuff here 
} 

template<size_t N> 
inline void doSomething(char (&charArray)[N]) 
{ 
    doSomething(charArray, N); 
} 

這種技術是由微軟的Secure CRT functions和STLSoft的array_proxy類模板使用。

5

它實際上曾經是一個相當常見的解決方案,用於傳遞數組第一個元素的長度。這種結構通常被稱爲BSTR(對於「基本字符串」),即使這也表示不同(但相似)的類型。

優於公認的解決方案的優點是,使用標記確定長度對於大型字符串來說很慢。缺點是顯然這是一種既不尊重類型,也不尊重結構的低級別攻擊。

在下面給出的格式中,它也只適用於長度爲< = 255的字符串。但是,通過將長度存儲在多個字節中,可以輕鬆擴展。

void doSomething(char* charArray) 
{ 
    // Cast unnecessary but I prefer explicit type conversions. 
    std::size_t length = static_cast<std::size_t>(static_cast<unsigned char>(charArray[0])); 
    // … do something. 
} 
5

一般用C或低級別的C工作++時,你可能會考慮再培訓你的大腦從來沒有考慮寫陣列參數的函數,因爲C編譯器總是把他們當作指針反正。從本質上講,通過輸入那些方括號,你就會想到真正的數組正在被傳遞,並附有大小信息。實際上,在C中你只能通過指針。功能

void foo(char a[]) 
{ 
    // Do something... 
} 

是,從C編譯器的角度來看,完全等效於:

void foo(char * a) 
{ 
    // Do something 
} 

並且顯然該nekkid字符指針不包含長度信息。

如果你被困在一個角落,並且不能改變函數簽名,可以考慮使用上面建議的長度前綴。非便攜式但兼容的黑客是指定數組長度位於size_t型場前陣,這樣的事情:

void foo(char * a) 
{ 
    int cplusplus_len = reinterpret_cast<std::size_t *>(a)[-1]; 
    int c_len = ((size_t *)a)[-1]; 
} 

顯然你的調用者需要通過他們之前在適當的方式來創建數組去富。

毋庸置疑,這是一個可怕的黑客攻擊,但這個伎倆可以擺脫困境在一個捏。

-1

您可以保證在32位個人電腦中收到4個,這是正確的答案。因爲解釋herehere的原因。 簡單的回答是,你實際上正在測試一個指針的大小而不是一個數組,因爲「該數組被隱式地轉換或衰減爲一個指針,指針,唉,不存儲數組的維度;它不會'你甚至可以告訴你所討論的變量是一個數組。「

既然您正在使用C++,boost::array是比原始數組更好的選擇。因爲它是一個對象,所以現在不會丟失尺寸信息。

-2

我認爲你可以這樣做:

size_t size = sizeof(array)/sizeof(array[0]); 

PS:我認爲這個專題的標題是不正確的,太。

-3

老兄你可以有一個全局變量來存儲整個程序可以訪問的數組的大小。至少你可以將數組的大小從main()函數傳遞給全局變量,並且甚至不必更改方法簽名,因爲大小將在全局範圍內可用。

請看例子:

#include<...> 
using namespace std; 

int size; //global variable 

//your code 

void doSomething(char charArray[]) 
{ 
    //size available 

} 
0

嘗試使用的strlen(charArray);使用cstring頭文件的 。這將產生包括空格在內的字符數量直到達到結尾「

相關問題