我可以在结构中使用 "int" 作为我的动态数组吗?

can i use "int" as my dynamic array inside a struct?

一般来说,我正在尝试分配 first.a 和 first.b 的值 在 struct secon.

中的数组
typedef struct {
    int a;
    int b;
} firs; 

//secon is my struct which contains dynamic array
//can i use int here ? 

typedef struct {
    int *aa;
    int *bb;
} secon;

//pointer to secon intialised to NULL;
secon* sp=NULL;

int main() 
{
    firs first;

    //plz assume 2 is coming from user ;
    sp=malloc(sizeof(secon)*2);

    //setting values 
    first.a=10;
    first.b=11;


    /* what i'm trying to do is assign values of first.a and first.b to my 
        dynamically created array*/

    /* plz assume first.a and first.b are changing else where .. that means ,not 
        all arrays will have same values */


    /* in general , i'm trying to allocate values of first.a and first.b
        to a array's in struct second. */

    for(int i=0; i<2; i++) {
        *( &(sp->aa ) + (i*4) ) = &first.a;
        *( &(sp->bb ) + (i*4) ) = &first.b;
    }

    for(int i=0; i<2; i++) {
        printf("%d %d \n", *((sp->aa) + (i*4) ),*( (sp->bb) +(i*4) ) );
    }

    return 0;
}

我的输出:

10 11 

4196048 0

我的代码有问题: 1.我的代码有什么问题? 2. 我可以在动态数组的结构中使用 int 吗? 3.有哪些选择? 4. 为什么我得不到正确答案?

这完全是一团糟。如果要访问 secon 的数组,请使用 []

for(int i=0;i<2;i++)
{
  sp[i].aa = &first.a; // Same pointer both times
  sp[i].bb = &first.b;
}

您有两个指向 first 中值的指针副本,它们指向相同的 value

for(int i=0;i<2;i++)
{
  sp[i].aa = malloc(sizeof(int)); // new pointer each time
  *sp[i].aa = first.a; // assigned with the current value 
  sp[i].bb = malloc(sizeof(int));
  *sp[i].bb = first.b;
}

但是编译器允许假设 first 不变,并且允许重新排序这些表达式,所以你不能保证你的 secons[=18= 中有不同的值]

无论哪种方式,当你读回第二个值时,你仍然可以使用 []

for(int i=0;i<2;i++)
{
  printf("%d %d \n",*sp[i].aa ),*sp[i].bb );
}

您对 C 中指针算法的工作原理的理解似乎有误。数据布局假设也存在问题。最后,存在可移植性问题和错误的语法选择,使理解变得复杂。

我假设机智这个表达式:*( &(sp->aa ) + (i*4) ) 你试图通过获取第 0 个项目的地址然后添加一个字节偏移量来访问数组中的第 i 个项目它。这是错误的三个原因:

  1. 你假设在内存中sp[0].aa之后是sp[1].aa,但是你忘记了中间还有sp[0].bb
  2. 您假设 int 的大小始终为 4 个字节,这是不正确的。
  3. 您假设将 int 添加到 secon* 将为您提供一个偏移指定字节数的指针,而实际上它将偏移指定数量的记录,大小为 secon.

您看到的第二行输出是来自未分配堆内存的随机垃圾,因为当 i == 1 您的构造引用的内存超出了为 *secon 分配的限制。

要访问指针引用的数组的第 i 项,请使用 []:

secon[0].aa等同于(secon +0)->aasecon[1].aa等同于(secon+1)->aa.

Grigory Rechistov 在理清代码方面做得非常出色,您可能应该接受他的回答,但我想强调一点。

在 C 指针算法中,偏移量总是以指向的类型的大小为单位。除非指针的类型是 char*void* 如果你发现自己乘以类型的大小,几乎可以肯定你做错了。

如果我有

int a[10];
int *p = &(a[5]);
int *q = &(a[7]);

那么a[6]就等于*(p + 1)不是*(p + 1 * sizeof(int))。同样 a[4]*(p - 1)

此外,当指针都指向同一个数组中的对象并且应用相同的规则时,您可以减去指针;结果以指向的类型的大小为单位。 q - p2,而不是 2 * sizeof(int)。将示例中的类型 int 替换为任何其他类型,并且 p - q 将始终为 2。例如:

struct Foo { int n ; char x[37] ; };
struct Foo a[10];
struct Foo *p = &(a[5]);
struct Foo *q = &(a[7]);

q - p 仍然是 2。顺便说一句,永远不要试图在任何地方对类型的大小进行硬编码。如果你想要 malloc 这样的结构:

struct Foo *r = malloc(41); // int size is 4 + 37 chars

不要。

首先,sizeof(int)不能保证是4。其次,即使是,sizeof(struct Foo)也不能保证是41。编译器通常会向struct类型添加填充以确保成员正确对齐。在这种情况下,几乎可以肯定编译器将在 struct Foo 的末尾添加 3 个字节(或 7 个字节)的填充,以确保在数组中,n 成员的地址对齐到 int 的大小。总是总是总是使用sizeof.