一般来说,我试图分配first.a和first.b的值 到结构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;
}
MY输出:
10 11
4196048 0
我的代码出现问题: 1.我的代码怎么了? 2.我可以在struct里面使用int for dynamic array吗? 3.有哪些替代方案? 4.为什么我没有得到正确答案?
答案 0 :(得分:3)
看起来您理解指针算术在C中的工作原理是错误的。数据布局假设也存在问题。最后,存在可移植性问题和错误的语法选择,这使得理解变得复杂。
我假设有这个表达式:*( &(sp->aa ) + (i*4) )
您试图通过获取第0个项的地址然后向其添加字节偏移来访问数组中的i
项。这有三个原因:
int
的大小始终为4个字节,这不是真的。int
添加secon*
将为您提供一个指定字节数偏移的指针,而实际上它将在指定数量的大小{{1}的记录中进行偏移}}。您看到的第二行输出是来自未分配堆内存的随机垃圾,因为当secon
您的构造引用超出为i == 1
分配的限制的内存时。
要访问由指针引用的第*secon
项数组,请使用i
:
[]
与secon[0].aa
相同,(secon +0)->aa
等于secon[1].aa
。
答案 1 :(得分:3)
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 - p
为2
,而不是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
唐&#39;吨。
首先,sizeof(int)
不能保证为4.其次,即使它是,sizeof(struct Foo)
也不能保证为41.编译器通常会向struct
类型添加填充以确保成员正确对齐。在这种情况下,几乎可以肯定的是,编译器会在struct Foo
的末尾添加3个字节(或7个字节)的填充,以确保在数组中n
成员的地址对齐大小为int。始终始终使用sizeof
。
答案 2 :(得分:2)
这是一个完整的混乱。如果您想访问secon
的数组,请使用[]
for(int i=0;i<2;i++)
{
sp[i].aa = &first.a; // Same pointer both times
sp[i].bb = &first.b;
}
您有两个指向first
中值的指针副本,它们指向相同的值
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;
}
但是,允许编译器假设第一个不会更改,并且允许重新排序这些表达式,因此您无法保证在secon
中具有不同的值
无论哪种方式,当您以秒为单位回读值时,仍然可以使用[]
for(int i=0;i<2;i++)
{
printf("%d %d \n",*sp[i].aa ),*sp[i].bb );
}