在c / c ++中处理可变大小数组的最佳实践?

时间:2008-10-10 02:16:27

标签: c++ c arrays

如果我有一个固定大小的数组,具体取决于它的定义和使用方式,我通常会使用两种方法之一来引用它。

数组类型1:由于它是基于定义的固定大小,我只是在引用它的所有循环中使用该定义。

#define MAXPLAYERS 4

int playerscores[MAXPLAYERS];

for(i=0;i<MAXPLAYERS;++i)
{
.... do something with each player
}

数组类型2:由于此数组可以随着项目的添加而增长,因此我使用sizeof来计算其中的条目数。编译器将大小转换为常量,因此不应该以这种方式执行任何运行时惩罚。

typedef struct
{
    fields....
}MYSTRUCT_DEF;

MYSTRUCT_DEF mystruct[]={
   {entry 1},
   {entry 2},
   {entry 3...n}
   };

 for(i=0;i<(sizeof(mystruct)/sizeof(MYSTRUCT_DEF));++i)
 {
 ..... do something with each entry
 }

是否有一个更优雅的解决方案来处理数组处理而不会过早结束或过早停止。思考?评论

9 个答案:

答案 0 :(得分:7)

无论数组元素类型如何,这都适用于您的两种情况:

#define ARRAY_COUNT(x) (sizeof(x)/sizeof((x)[0]))

...

struct foo arr[100];
...

for (i = 0; i < ARRAY_COUNT(arr); ++i) {
    /* do stuff to arr[i] */
}

答案 1 :(得分:5)

在C ++中,只需使用矢量类。

如果由于某种原因你不能,那么就有你想要的宏实现。 请参阅此答案,了解winnt.h中的一组宏,这些宏在C语言中工作,在C ++中更安全:

Can this macro be converted to a function?

答案 2 :(得分:5)

使用stdlib.h的_countof宏

From this MSDN article

// crt_countof.cpp
#define _UNICODE
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
int main( void )
{
   _TCHAR arr[20], *p;
   printf( "sizeof(arr) = %d bytes\n", sizeof(arr) );
   printf( "_countof(arr) = %d elements\n", _countof(arr) );
   // In C++, the following line would generate a compile-time error:
   // printf( "%d\n", _countof(p) ); // error C2784 (because p is a pointer)

   _tcscpy_s( arr, _countof(arr), _T("a string") );
   // unlike sizeof, _countof works here for both narrow- and wide-character strings
}

答案 3 :(得分:2)

看到像

这样的C代码是相当普遍的
struct foo {
    ...  /* fields */
};
struct foo array[] = {
    { ... }, /* item 1 */
    { ... }, /* item 2 */
    ...,
    { 0 } /* terminator */
};
for (i = 0; array[i].some_field; i++) {
    ...
}

通常,您可以找到至少一个对于普通元素永远不会0 / NULL的字段,如果没有,您可以使用其他一些特殊的END值。

在我编写的代码中,涉及编译时大小数组的任何内容都是使用来自Checkers的答案的ARRAY_COUNT之类的宏完成的,而运行时大小的数组总是带有一个大小计数器,在带有数组的结构中。

struct array_of_stuff {
    struct stuff *array;
    int count;   /* number of used elements */
    int length;  /* number of elements allocated */
};

length字段允许轻松批量调整大小。

答案 4 :(得分:1)

对于C,我建议realloc动态引入新变量。如果你是静态地做某事,我建议保持#define。我不确定我是否会称之为最佳实践,但是,今天,我就是这样做的。

C ++最佳实践是使用stl :: vector。 A reference here

答案 5 :(得分:1)

除非有特殊原因,否则我几乎总是使用包装类(MFC CArray,stl向量等)。没有太多的开销,你可以进行大量的调试检查,你可以动态调整大小,获得大小很容易等等。

答案 6 :(得分:1)

对于C ++,使用std :: vector

使用C阵列没有任何意义。 std :: vector具有(几乎)与C数组相同的性能,它将:

  • 根据需要增长
  • 知道它的大小
  • 验证您确实正在访问正确的内存(例如,如果超出其范围,它可能会抛出异常)

这甚至没有考虑与std :: vector相关的通用算法。

现在,使用C

至少在两个方面你可以写得更好一些。首先,用真正的常量变量替换define:

// #define MAXPLAYERS 4
const unsigned int MAXPLAYERS = 4 ;

int playerscores[MAXPLAYERS];

for(i=0;i<MAXPLAYERS;++i)
{
.... do something with each player
}

使用true变量将提供更多的类型安全性,并且不会污染全局范围。要最小化依赖性,您甚至可以在标头中声明变量,并在源中定义它们:

/* header.h */
extern const unsigned int MAXPLAYERS ;
extern int playerscores[] ;

/* source.c */
const unsigned int MAXPLAYERS = 4
int playerscores[MAXPLAYERS];

/* another_source.c */
#include "header.h"

for(i=0;i<MAXPLAYERS;++i)
{
.... do something with each player
}

这样,您就可以在一个源中更改数组的大小,而无需重新编译使用它的所有源。缺点是MAXPLAYERS在编译时不再是已知的(但是,这真的是一个缺点吗?)

请注意,您的第二种类型的数组无法动态增长。在编译时评估sizeof(至少在C ++中)。对于增长的数组,malloc / realloc / free是C语言的方法,而std :: vector(或任何其他通用的STL容器)是C ++的用法。

答案 7 :(得分:1)

请务必阅读this question's answers - 可移植的数组大小问题的许多解决方案。

我特别喜欢_countof(cfr.Brian R. Bondy的回答) - 普利策为这个名字的发明者!

答案 8 :(得分:0)

如果您在C ++中使用T []数组,那么到目前为止,除了答案之外: 使用模板参数推导来推导数组大小。它更安全:

template<int N> void for_all_objects(MYSTRUCT_DEF[N] myobjects)

如果将mystruct更改为malloc'ed / new'ed sizeof(mystruct)/sizeof(MYSTRUCT_DEF),则MYSTRUCT_DEF*表达式会非常默默地失败。 sizeof(mystruct)然后变为sizeof(MYSTRUCT_DEF*),通常小于sizeof(MYSTRUCT_DEF),并且你的循环次数为0.看起来代码根本就没有被执行,这可能非常令人困惑。上面的模板声明将为您提供明确的编译器错误(“mystruct不是数组”)