重命名(别名)C语言数组元素

4

不确定什么是“好的实践”或被认为更“正确”。我有一个数组,我想通过名称访问单个元素而不是arrayname[]。我可以使用#define或指针,也可能有其他方法。

例如:

#define value1 myarray[1]

int myarray[SIZE];
value1 = 5;

或者

int myarray[SIZE];
int *ptr;
ptr = &myarray[1];
*ptr = 5;

似乎对我来说,使用#define路线更简单且占用更少的内存,但可能会引起我不知道的一堆问题。如果有任何建议,那就太好了,我希望我的代码在可能的情况下遵循普遍接受的标准。
*编辑:也许有一个更好的方法。我的最终目标是获得一个将发送到外围端口的数组。然而,数据由非常不同的数据集组成,一个单一的数组名称不能代表分配的数据。我的内存非常有限,所以我想避免每个值都进行双重存储。

4
天啊,这维护简直是个噩梦! - dmckee --- ex-moderator kitten
为什么你想这么做?这有什么理由吗? - didierc
5
我认为,如果一个值需要与数组中所有其他值不同的身份标识,那么这个值本应该不在数组中。你能提供一个更具体的例子来展示你的想法有用吗? - Kevin
相关链接:http://stackoverflow.com/q/1103299/2509 - dmckee --- ex-moderator kitten
这肯定会成为维护的噩梦。你为什么要这样做? - Rutix
6个回答

5
我提议第三种选择,例如:
#define VALUE1_IDX  1

int myarray[SIZE];
myarray[VALUE1_IDX] = 5;

与#1相比,其优点在于仍然明显地使用了myarray,并且与#2相比的优点正如您所说,避免了指针。我怀疑,但尚未验证,在优化方面,选项#2将不会有额外的内存使用,尽管这似乎很直观。
我认为最好的解决方案会因情况而异,我认为在合适的情况下,您两个选项都是明智的。
编辑:回应Kevin的评论,首先值得检查的是是否有可能在不集体处理值时避免使用数组。我意识到肯定存在一些不适用的情况,例如如果您读取了一条长消息并想简单地提取几个关键值。

这看起来非常有前途,而且很明显,不知道为什么我没想到。保持数组名称通用,但使用描述性的索引值将使我获得所需的结果。感谢您的建议。 - abrand

2
为什么不使用引用?
int A[3];  
int& a1=A[1];

1

union是另一种给变量取别名的方式。但不要把它看作是推荐的做法。如果你依赖于别名,它们是危险的(不可移植的)。你应该只在需要优化内存使用的变量上使用它们,而这些变量不需要同时使用。


一个联合体不允许你别名一个已经存在的变量。此外,使用联合体使两个对象别名可能会违反严格别名规则(取决于类型),并且由于联合体中只有一个成员处于“活动”状态的规则,这种做法也是值得商榷的。 - bames53

1
enum {SIZE = 100};

struct Mapping {
  int unused1;
  int value1;
  int unused2;
};

Mapping& AsMapping( int(&array)[SIZE] ) {
  return *reinterpret_cast<Mapping*>(&array);
}

int arr[SIZE];
AsMapping(arr).value1 = 5;
Mapping& values = AsMapping(arr);
values.value1 = 5;

这几乎不需要任何内存,优化器应该能够清除所有内容。同时,它也相当易于维护。

在您的struct上设置对齐可能是一个需要小心处理的要求。


0

非定义方法允许您获得第二种方法无法提供的一定程度的类型纠正。

此外,任何合理编译器生成的实际代码都将是相同的。

总的来说,我更喜欢第二种方法,因为它可以立即明确正在发生的事情。另一个问题是#define可能会在您实际处理的区域范围之外引起问题。

使用后者更加明智,因为这意味着其他人在以后的某个场合不太可能犯错...


0
你可以像这样做:
typedef enum
{
    foo = 0;
    // ... more named values
    bar = SIZE;
} Thing;

int value[SIZE];
value[foo] = 5;

将枚举用作数组索引


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