2009-08-13 102 views
17

如果我有一個原型,看起來像這樣:如何將一個常量數組文字傳遞給一個不帶變量C/C++的指針的函數?

function(float,float,float,float) 

我可以通過數值是這樣的:

function(1,2,3,4); 

所以,如果我的原型是這樣的:

function(float*); 

有什麼我可以實現這樣的事情嗎?

function({1,2,3,4}); 

只是尋找一種懶惰的方式來做到這一點,而不創建一個臨時變量,但我似乎無法指定語法。

+0

感謝您的建議。我想我預計一個快速和骯髒的問題的快速和骯髒的答案,但你的迴應探討了一些我沒有想到的替代風格。非常感激! – sinoth 2009-08-13 01:54:10

回答

27

你可以做到這一點在C99(但不ANSI C(C90)或任何CURR C++的變體)與複合文字。有關血淋淋的詳細信息,請參閱C99標準的第6.5.2.5節。這裏有一個例子:

// f is a static array of at least 4 floats 
void foo(float f[static 4]) 
{ 
    ... 
} 

int main(void) 
{ 
    foo((float[4]){1.0f, 2.0f, 3.0f, 4.0f}); // OK 
    foo((float[5]){1.0f, 2.0f, 3.0f, 4.0f, 5.0f}); // also OK, fifth element is ignored 
    foo((float[3]){1.0f, 2.0f, 3.0f}); // error, although the GCC doesn't complain 
    return 0; 
} 

GCC也提供這個作爲C90的擴展。如果編譯時使用-std=gnu90(默認值),-std=c99-std=gnu99,則會編譯;如果使用-std=c90進行編譯,則不會。

+0

顯然也可以用'-std = gnu89'(但不是'-std = c89')編譯,因爲它與'-std = gnu90'同義(和'-std = c90')(我相信你知道這個亞當,對於其他人來說更是如此,以防他們沒有:P)。 – RastaJedi 2016-08-27 04:35:25

2

壞消息是,沒有語法。好消息是,這將隨着C++標準的下一個正式版本(將在未來一兩年內發佈)而改變。新的語法看起來和你描述的完全一樣。

+1

嘿嘿,明年或兩年:]很高興知道這將在C++ 0x。 – sinoth 2009-08-13 01:46:05

+0

我懷疑在兩年內。 Visual Studio的Beta 10已經內置了一些C++ 0x功能,並且g ++ 4.4已經有了初始化列表(http://gcc.gnu.org/projects/cxx0x.html)。它被推回到2010年,可能是第一季度。 – GManNickG 2009-08-13 01:58:25

0

不,你不能那樣做。我沒有可用的標準在這裏,所以我不能給出一個確切的參考,但最接近你問什麼是字符串常量,即

function(char *); 
function("mystring"); 

是由編譯器視爲

char * some_pointer = "mystring"; 
function(char *); 
function(some_pointer); 

用這種方法處理其他類型的變量是沒有辦法的。

4

您可以創建文字的化合物:

function ((float[2]){2.0, 4.0}); 

雖然,我不知道你爲什麼要經歷的麻煩。 ISO不允許這樣做。

一般而言,應該避免使用像這樣的快捷方式,以利於所有情況下的可讀性;懶惰是不是探索一個好習慣(個人意見,當然)

+0

我同意可讀性,實際上這個特定的函數會傳遞一個內存地址並且很高興。但是,在測試期間,我經常想插入一些隨機值。你的代碼片斷會訣竅,更好或更糟:)謝謝! – sinoth 2009-08-13 01:42:12

+2

這是在c99中有效,但沒有別的標準明智... – 2009-08-13 02:42:04

0

可悲的是,它僅適用於字符數組:

void func2(char arg[]) { 
} 

int main() 
{ 
    func2("hello"); 
    return 0; 
} 
17

這標誌着C和C++,所以你會得到根本不同的答案。

如果你期待四個參數,你可以這樣做:

void foo(float f[]) 
{ 
    float f0 = f[0]; 
    float f1 = f[1]; 
    float f2 = f[2]; 
    float f3 = f[3]; 
} 

int main(void) 
{ 
    float f[] = {1, 2, 3, 4}; 
    foo(f); 
} 

但是,這是相當不安全的,因爲你可以通過事故做到這一點:

void foo(float f[]) 
{ 
    float f0 = f[0]; 
    float f1 = f[1]; 
    float f2 = f[2]; 
    float f3 = f[3]; 
} 

int main(void) 
{ 
    float f[] = {1, 2}; // uh-oh 
    foo(f); 
} 

通常最好離開他們作爲個人參數。既然你不應該使用原始數組,你可以這樣做:

#include <cassert> 
#include <vector> 

void foo(std::vector<float> f) 
{ 
    assert(f.size() == 4); 

    float f0 = f[0]; 
    float f1 = f[1]; 
    float f2 = f[2]; 
    float f3 = f[3]; 
} 

int main(void) 
{ 
    float f[] = {1, 2, 3, 4}; 
    foo(std::vector<float>(f, f + 4)); // be explicit about size 

    // assert says you cannot do this: 
    foo(std::vector<float>(f, f + 2)); 
} 

一個改進,但沒有太大的一個。你可以使用boost::array,但不是不匹配的大小錯誤,它們被初始化爲0:

#include <boost/array.hpp> 

void foo(boost::array<float, 4> f) 
{ 
    float f0 = f[0]; 
    float f1 = f[1]; 
    float f2 = f[2]; 
    float f3 = f[3]; 
} 

int main(void) 
{ 
    boost::array<float, 4> f = {1, 2, 3, 4}; 
    foo(f); 

    boost::array<float, 4> f2 = {1, 2}; // same as = {1, 2, 0, 0} 
    foo(f2); 
} 

這都將是固定的C++ 0x中,當初始化列表構造函數中添加:

#include <cassert> 
#include <vector> 

void foo(std::vector<float> f) 
{ 
    assert(f.size() == 4); 

    float f0 = f[0]; 
    float f1 = f[1]; 
    float f2 = f[2]; 
    float f3 = f[3]; 
} 

int main(void) 
{ 
    foo({1, 2, 3, 4}); // yay, construct vector from this 

    // assert says you cannot do this: 
    foo({1, 2}); 
} 

,可能boost::array還有:

#include <boost/array.hpp> 

void foo(boost::array<float, 4> f) 
{ 
    float f0 = f[0]; 
    float f1 = f[1]; 
    float f2 = f[2]; 
    float f3 = f[3]; 
} 

int main(void) 
{ 
    foo({1, 2, 3, 4}); 

    foo({1, 2}); // same as = {1, 2, 0, 0} ..? I'm not sure, 
       // I don't know if they will do the check, if possible. 
} 
0

你可以寫一個生成器類,將允許大約相同的語法

// roughly 
template <typename C> 
class Builder { 
public: 
    template <typename T> 
    Builder(const T & _data) { C.push_back(_data); } 
    template <typename T> 
    Builder& operator()(const T & _data) { 
     C.push_back(_data); 
     return *this; 
    } 
    operator const C &() const { return data; } 
private: 
    C data; 

}; 

這樣,你就可以使用類作爲

富(常量的std ::向量& V);

foo(Builder < std :: vector>(1)(2)(3)(4));

2

你可以在技術上引用數組,但你仍然不能創建我認爲的匿名初始化列表。

void func(int (&bla)[4]) 
{ 
    int count = sizeof(bla)/sizeof(bla[0]); 
    // count == 4 
} 

int bla[] = {1, 2, 3, 4}; 
func(bla); 

int bla1[] = {1, 2}; 
func(bla1); // <-- fails 

對於C++方式,請看boost::assign。填充STL容器的方式非常簡潔。

0

要增加樂趣,您可以使用模板使其長度可變。

template<std::size_t N> 
int chars(const char(&r)[N]){ 
    std::cout << N << ": " << r << std::endl; 
    return 0; 
} 

template<std::size_t N> 
int floats(const float(&r)[N]){ 
    std::cout << N << ":"; 
    for(size_t i = 0; i < N; i++) 
     std::cout << " " << r[i]; 
    std::cout << std::endl; 
    return 0; 
} 

int main(int argc, char ** argv) { 
    chars("test"); 
    floats({1.0f, 2.0f, 3.0f, 4.0f}); 
    return 0; 
} 
相關問題