web-dev-qa-db-ja.com

Cの配列に複数の値を割り当てます

これを凝縮した形で行う方法はありますか?

GLfloat coordinates[8];
...
coordinates[0] = 1.0f;
coordinates[1] = 0.0f;
coordinates[2] = 1.0f;
coordinates[3] = 1.0f;
coordinates[4] = 0.0f;
coordinates[5] = 1.0f;
coordinates[6] = 0.0f;
coordinates[7] = 0.0f;
return coordinates;

何かのようなもの coordinates = {1.0f, ...};

28
UnstableFractal

本当にassign values(initializeとは対照的に)にしたい場合は、次のようにできます:

 GLfloat coordinates[8]; 
 static const GLfloat coordinates_defaults[8] = {1.0f, 0.0f, 1.0f ....};
 ... 
 memcpy(coordinates, coordinates_defaults, sizeof(coordinates_defaults));

 return coordinates; 
26
James Curran

昔ながらの方法:

GLfloat coordinates[8];
...

GLfloat *p = coordinates;
*p++ = 1.0f; *p++ = 0.0f; *p++ = 1.0f; *p++ = 1.0f;
*p++ = 0.0f; *p++ = 1.0f; *p++ = 0.0f; *p++ = 0.0f;

return coordinates;
11
Pavel Minaev

配列を構造体にラップするトリックがあります(宣言後に初期化できます)。

すなわち。

struct foo {
  GLfloat arr[10];
};
...
struct foo foo;
foo = (struct foo) { .arr = {1.0, ... } };
11
domen

次を使用できます。

GLfloat coordinates[8] = {1.0f, ..., 0.0f};

しかし、これはコンパイル時の初期化です-現在の標準でそのメソッドを使用して再初期化することはできません(今後の標準でそれを行う方法はあると思いますが、すぐには役に立たないかもしれません)。

頭に浮かぶ他の2つの方法は、内容が修正されている場合は内容を削除することです。

GLfloat base_coordinates[8] = {1.0f, ..., 0.0f};
GLfloat coordinates[8];
:
memcpy (coordinates, base_coordinates, sizeof (coordinates));

とにかく初期化コードのように見える関数を提供します:

void setCoords (float *p0, float p1, ..., float p8) {
    p0[0] = p1; p0[1] = p2; p0[2] = p3; p0[3] = p4;
    p0[4] = p5; p0[5] = p6; p0[6] = p7; p0[7] = p8;
}
:
setCoords (coordinates, 1.0f, ..., 0.0f);

これらの楕円(...)はプレースホルダーであり、文字通りコードに挿入するものではありません。

4
paxdiablo

まさに、あなたはそれをほぼ手に入れました:

GLfloat coordinates[8] = {1.0f, ..., 0.0f};
3
Felix Kling

プログラムでこれらの同じ割り当てを頻繁に行っており、ショートカットが必要な場合、最も簡単な解決策は関数を追加することです

static inline void set_coordinates(
        GLfloat coordinates[static 8],
        GLfloat c0, GLfloat c1, GLfloat c2, GLfloat c3,
        GLfloat c4, GLfloat c5, GLfloat c6, GLfloat c7)
{
    coordinates[0] = c0;
    coordinates[1] = c1;
    coordinates[2] = c2;
    coordinates[3] = c3;
    coordinates[4] = c4;
    coordinates[5] = c5;
    coordinates[6] = c6;
    coordinates[7] = c7;
}

そして、単に呼び出す

GLfloat coordinates[8];
// ...
set_coordinates(coordinates, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f);
0
dpi

このようなコードでは:

const int node_ct = 8;
const int expected[node_ct] = { 1, 3, 4, 2, 5, 6, 7, 8 };

そして、configure.ac

AC_PROG_CC_C99

私の開発ボックスのコンパイラは満足でした。サーバー上のコンパイラは次のように不平を言いました:

error: variable-sized object may not be initialized
   const int expected[node_ct] = { 1, 3, 4, 2, 5, 6, 7, 8 };

そして

warning: excess elements in array initializer
   const int expected[node_ct] = { 1, 3, 4, 2, 5, 6, 7, 8 };

各要素

たとえば、まったく文句を言いません。

int expected[] = { 1, 2, 3, 4, 5 };

しかし、サイズのチェックが好きだと決めました。

戦うのではなく、可変引数の初期化子を使用しました。

#include <stdarg.h>

void int_array_init(int *a, const int ct, ...) {
  va_list args;
  va_start(args, ct);
  for(int i = 0; i < ct; ++i) {
    a[i] = va_arg(args, int);
  }
  va_end(args);
}

と呼ばれる、

const int node_ct = 8;
int expected[node_ct];
int_array_init(expected, node_ct, 1, 3, 4, 2, 5, 6, 7, 8);

そのため、可変引数のサポートは、配列初期化子のサポートよりも堅牢です。

誰かがマクロでこのようなことをすることができるかもしれません。

https://github.com/wbreeze/davenport/pull/15/files でサンプルコードを使用してPRを見つける

https://stackoverflow.com/a/3535455/608359 @paxdiabloから、私はそれが好きでした。しかし、初期化ポインターが進む回数を配列に割り当てられた要素の数と同期させることに不安を感じました。最悪の場合、初期化ポインタは割り当てられた長さを超えて移動します。そのため、PRの差分には、

  int expected[node_ct];
- int *p = expected;
- *p++ = 1; *p++ = 2; *p++ = 3; *p++ = 4;
+ int_array_init(expected, node_ct, 1, 2, 3, 4);

int_array_initメソッドは、引数の数がnode_ctより少ない場合、ジャンクを安全に割り当てます。迷惑メールの割り当ては、キャッチとデバッグが簡単である必要があります。

0
Douglas Lovell