2009-08-13 24 views
17

私はこのようになりますプロトタイプがある場合:私のプロトタイプはこれですのであれば変数C/C++を使用せずにポインタを取る関数に定数配列リテラルを渡すには?

function(1,2,3,4); 

function(float*); 

は、任意のはあります

function(float,float,float,float) 

を私はこのような値を渡すことができます私はこれのような何かを達成することができますか?

一時変数を作成せずにこれを行うための怠惰な方法を探していますが、構文を釘付けにすることはできません。

+0

アドバイスありがとうございます。私は迅速かつ汚れた質問のために迅速かつ汚れた回答を期待していたと思いますが、あなたの回答は私が考えていなかったいくつかの代替スタイルを模索しました。とても有難い! – sinoth

答えて

27

あなたはC99(しかしない ANSI C(C90)、または任意のCURRでそれを行うことができますC++のentバリアント)化合物リテラル。詳細については、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でコンパイルすると、それはされません。あなたはこのよう

同じ構文について
// 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; 

}; 

を可能にするビルダークラスを記述することができます

+0

'-std = gnu89'と同義であるため、' -std = gnu89'( '-std = c89'ではなく)でコンパイルすることもできます。 (そして '-std = c90')(私はあなたがこのアダムを知っていると確信しています。 – RastaJedi

2

悪い知らせは、そのための構文がないということです。良いニュースは、これがC++標準の次の正式版(来年2月に予定)で変わるということです。新しい構文は、あなたが記述した通りに正確に見えます。

+1

heh heh、来年または2:]これはC++ 0xであることを知っておいてください。 – sinoth

+0

私は2年で疑問です。 Visual StudioのBeta 10には既にC++ 0x機能が組み込まれており、g ++ 4.4には初期設定リスト(http://gcc.gnu.org/projects/cxx0x.html)が既に用意されています。おそらく第1四半期、2010年に戻った。 – GManNickG

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

+2

これはc99で有効ですが、他には標準的なものはありません... –

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)); 
} 

改善が、しかし、1つのあまりありません:あなたはとにかく生の配列を使用してはならないので、あなたはこれを行うことができます。あなたは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

、あなたは

のfoo(constのは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 

については、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; 
} 
関連する問題