在C语言中为数组分配多个值

47

有没有简洁的方法来实现这个?

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, ...};


1
你在那里返回一个局部变量的指针吗?下面一些人在答案/评论中说的话假定涉及的变量是自动变量或不是自动变量。如果你能明确说明可能会有所帮助。 - Steve Jessop
一旦结构体被初始化,除了使用memcpy复制另一个结构体之外,没有简单的方法来批量分配成员。我经常发现自己希望有这个功能。 - bta
我认为你的原始答案是最好的 - 它很直观,虽然有点冗长,但对于现代编译器来说这不是问题。 - Yan King Yin
8个回答

36

如果你真的要赋值(而不是初始化),可以按照以下方式执行:

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

 return coordinates; 

2
最好使用“static const”,编译器可以将变量优化掉,从而使代码更加高效。 - Zan Lynx
@Zan Lynx:大多数编译器不都会自动处理这个吗?哦,好吧。我想明确一下也是个好习惯。 - Chris Cooper
1
@Chris Cooper:如果它是全局的(可能在编译器看不到的代码中被修改),那就不一定了。从这些代码片段中,你无法确定“...”是否省略了函数的开头。 - Steve Jessop
@Steve:好的决定。谢谢你澄清。 - Chris Cooper

22
尽管在您的情况下,仅仅进行简单的初始化就可以了,但有一种将数组装入结构体的技巧(可以在声明后进行初始化)。

例如:

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

12

老派的方法:

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;

优雅,我承认,但管理一些合理的初始化数据集(最终需要调整它们)将会很麻烦。我更喜欢一些语法,只需要数据(可能还有一些可见性分隔符)就足够了。此外,这是指针算术。MISRA 对此会感到疯狂。 - OpalApps

4

您可以使用:

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

但这是编译时初始化,您无法在当前标准中使用该方法重新初始化(尽管我认为有办法在即将发布的标准中实现它,但可能不会立即对您有帮助)。
另外两种方法是如果内容固定,则可以将其覆盖:
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

我选择了数组初始化方法:

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

C99 数组初始化如下所示:
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 };

我喜欢对大小的检查,并且varargs支持比数组初始化程序的支持更加健壮。

https://github.com/wbreeze/davenport/pull/15/files中找到带有示例代码的PR。

关于@paxdiablo的https://dev59.com/pnA65IYBdhLWcg3w-jym#3535455,我很喜欢,但是感到不安,因为初始化指针移动的次数与分配给数组的元素数量同步。最坏的情况是初始化指针超过了分配的长度。因此,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),将会执行这个操作。垃圾赋值应该更容易被发现和调试。


2
我点赞是因为你使用了可变参数的方法,这使得代码更易读。 但是它有点被埋没在你的回答中。也许你应该编辑一下你的帖子,给它应有的关注。 - Faibbus

3

没错,你接近正确答案了:

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

4
那个语法只适用于声明。 - Michael Mrozek
这很糟糕.. 有没有其他简化的方法? :) - UnstableFractal

0

如果你在程序中经常执行这些相同的任务并想要一个快捷方式,最直接的解决方案可能就是添加一个函数。

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

-1
typedef struct{
  char array[4];
}my_array;

my_array array = { .array = {1,1,1,1} }; // initialisation

void assign(my_array a)
{
  array.array[0] = a.array[0];
  array.array[1] = a.array[1];
  array.array[2] = a.array[2];
  array.array[3] = a.array[3]; 
}

char num = 5;
char ber = 6;

int main(void)
{
  printf("%d\n", array.array[0]);
// ...

  // this works even after initialisation
  assign((my_array){ .array = {num,ber,num,ber} });

  printf("%d\n", array.array[0]);
// ....
  return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接