在C语言中使用结构访问数组

在C语言中使用结构访问数组,c,arrays,structure,C,Arrays,Structure,我了解如何创建可用于访问数组的结构,例如: #include <stdio.h> typedef struct { int i; int j; int k; } MyStruct; int main() { MyStruct *ms; int array[9]; int i; for(i=0;i<9;++i) array[i] = i; ms = (MyStruct *)array; for(i=0;i<3;++i) prin

我了解如何创建可用于访问数组的结构,例如:

#include <stdio.h>

typedef struct {
  int i;
  int j;
  int k;
} MyStruct;

int main()
{
  MyStruct *ms;
  int array[9];
  int i;

  for(i=0;i<9;++i) array[i] = i;

  ms = (MyStruct *)array;

  for(i=0;i<3;++i) printf("%d %d %d %d\n",i,ms[i].i,ms[i].j,ms[i].k);
  return 0;
}
#包括
类型定义结构{
int i;
int j;
int k;
}我的结构;
int main()
{
MyStruct*ms;
int数组[9];
int i;

对于(i=0;i简单来说,给定数组大小
N
myArgs
,您将拥有
N/myArgs
完整的数据集,以及剩余的
N%myArgs
项。您可以根据这一事实建立数组索引

然而,这段代码看起来像是一场维护噩梦。你想完成什么?可能有更好的方法。

在第一种情况下,结构的大小是3个
int
变量的大小。当您将数组指针转换为结构的指针时,每3个
int
元素将与一个
MyStruct
元素相匹配,代码中的魔力是什么(理论上是不可移植的)

在第二种情况下,结构的大小是指向
int
的1个指针的大小。您必须知道指针在用法上与数组有一些相似之处,但它们不是同一件事。指针只是一个变量,具有指向内存地址的单个值。然后该地址的内容可以用作数组

在C语言中,结构和数组的大小是在编译时处理的,因此结构的大小在运行时不能改变,因此在结构中放置指针对您的目的没有好处,因为指针大小也是固定的

可能一个好的解决方案是使用抽象数据类型,如:

typedef struct {
  int m; /* number of lines */
  int n; /* number of columns */
  int *data; /* pointer to the actual data */
} Matrix;
然后,您可以创建用于使用结构的辅助函数:

void matrix_new(Matrix *m, int rows, int columns);
int matrix_get(Matrix *m, int i, int j);
void matrix_set(Matrix *m, int i, int j, int value);
void matrix_free(Matix *m);
如果这太笨拙,您甚至可以使用混合方法(不太“抽象”类型):

int矩阵(矩阵*m,int i,int j)
{
返回m->data[i*m->n+j];
}
int main()
{
矩阵m;
int数组[9];
int i;

对于(i=0;i根据您的说明,我将按如下方式处理问题。我将有一个同时具有固定x、y和z的结构,然后是一个指向数组的指针,您可以将其设置为解决方案数组中相应点的位置。类似于这样的内容:

struct MyStruct {
    int x, y, z;
    int *extras;
};

...
int solutions[9];
struct MyStruct ms;
ms.x = solutions[0];
ms.y = solutions[1];
ms.z = solutions[2];
ms.extras = (solutions + 3);
...
通过这种方式,您可以轻松访问所需的字段,以及诸如:

ms.extras[0]
至少那应该行得通,在我脑子里

如果我是你,我也会在结构中加入num_extras,这样你就不会跑完数组的末尾

编辑:如果您希望对其进行镜像,可以改为:

struct MyStruct {
    int *x, *y, *z;
    int *extras;
};
然后有:

...
int solutions[9];
struct MyStruct ms;
ms.x = &solutions[0];
ms.y = &solutions[1];
ms.z = &solutions[2];
ms.extras = (solutions + 3);
...

但这与您以前的情况非常相似,不是吗?

只是出于好奇,为什么要在实际代码中这样做?所有这些都是无效的;都是未定义的行为。问题需要澄清。如果数组是来自某种外部设备的缓冲区,并且您正在覆盖一个结构数组,那么您可能需要这样做这是正确的。数组来自另一个库,我只想提供一个“窗口”看看它,如果这更有意义的话。关于@KerrekSB的评论,这段代码以严格的别名中断。如果您使用较新的gcc编译它,或者使用带有
-fstrict别名的较旧的gcc编译它,您可能会得到虚假的结果。我愿意接受关于提供方便访问的更好方法的建议。我工作的其他所有人都来自fortran background,因此使库易于理解/使用是至关重要的。即使这意味着我在后端有更多的维护工作要做。但这不会复制数据吗?它将同时存在于原始阵列和结构中,因此对ms.x的更改不会反映在解决方案[0]中,反之亦然。
struct MyStruct {
    int *x, *y, *z;
    int *extras;
};
...
int solutions[9];
struct MyStruct ms;
ms.x = &solutions[0];
ms.y = &solutions[1];
ms.z = &solutions[2];
ms.extras = (solutions + 3);
...