【问题标题】:2 different weird errors with struct assignment结构赋值的 2 个不同的奇怪错误
【发布时间】:2020-05-08 20:42:08
【问题描述】:

拥有此代码:

#include <stdio.h>
#include <stdlib.h>

struct Test { char c; } foo;

int main (void) {

   struct Test *ar[10];
   struct Test *(*p)[] = &ar; //what type of syntax is this *(*p)[]

   *(*p+1) = &foo; // the same  (*p)[1] = &foo
   //this only works


   p[0][1] = &foo  //the same as *(*p+1) 
   ////1error: invalid use of array with unspecified bounds

   (*(*p+1)+1) = &foo // the same as p[1][1] = &foo 
   ////2error: lvalue required as left operand of assignment

   //HOW TO make assignment of p[1][1] = &foo   and NOT p[0][1] ??

   return 0;
}

尝试将地址从结构分配到结构数组时,我遇到了 2 个奇怪的错误。我想要错误解释以及如何将分配(即代码)分配给p[1][1]

编辑:the same as 语句可能是错误的。我只是想,如果“正常”指针(它们的类型),它们将是平等的

【问题讨论】:

  • 哎哟!指向指针数组的指针——大小不确定。这将很难解释。可以做到,但并不容易。我不相信您的“与” cmets 一样,尤其是第一个。
  • @JonathanLeffler 是的,第一个完全错误,不是吗? (*p)[0]*(*p) 相同。那里没有+1
  • @JonathanLeffler 他们可能是错的,如果是这样,就这么说
  • 但是我的意思是,为什么他们错了,如果“普通指针”或者他们都是正确的?
  • 我主要是在说“我的脑痛”和 TGIF。对你来说好消息是你不太可能在野外遇到任何如此深奥的东西——人们通常不会编写这样的代码,尤其是因为它很难理解和正确。我将坐在场边,直到几个小时后。我希望有人能帮我找出问题所在。

标签: c arrays pointers struct


【解决方案1】:

逐行回答你的cmets:

#include <stdio.h>
#include <stdlib.h>

struct Test { char c; } foo;

int main (void) {

   struct Test *ar[10];
   struct Test *(*p)[] = &ar; //what type of syntax is this *(*p)[]

cdecl.org 表示struct Test *(*p)[] 表示declare p as pointer to array of pointer to struct Test。顺便说一句,数组是一个未知/未指定大小的数组,因为方括号中没有任何内容。

   *(*p+1) = &foo; // the same  (*p)[1] = &foo
   //this only works

你是对的,是的,它有效。

   p[0][1] = &foo;  //the same as *(*p+1) 
   ////1error: invalid use of array with unspecified bounds

(我添加了你缺少的分号。)你通常是对的,但在这种情况下,有点迂腐意味着你不是。 x[0] 不等同于*x,而是*(x + 0)。这些通常是等价的,但是当x 是一个指向未知大小的指针时,你不能对其进行指针运算。

   (*(*p+1)+1) = &foo; // the same as p[1][1] = &foo 
   ////2error: lvalue required as left operand of assignment

(我再次添加了您丢失的分号。)不完全是。 p[1][1] 将是 *(*(p+1)+1)。你的*s 和括号是错误的。

   //HOW TO make assignment of p[1][1] = &foo   and NOT p[0][1] ??

你不知道*p指向的数组有多大。

   return 0;
}

【讨论】:

  • 所以如果我确定了尺寸说struct Test *(*p)[10] = &amp;ar,那么它会起作用吗?
  • p[1][1] 给了我堆栈粉碎。 *(*(p+1)+1) = &amp;foo; 但我分配的空间来自语句 `struct Test *(*p)[10] = &ar;`,
  • @Herdsman 对不起,让我澄清一下。我的意思是“工作”,就像“对编译器有效”一样。这不会在运行时执行您想要的操作,因为您只有一个数组,但 p[1] 将尝试访问不存在的第二个数组。
  • 那么我如何分配新数组来添加第二个需要的空间来实现上述目标,比如realloc(p, sizeof(&amp;p)*2)
  • @Herdsman struct Test *ar[2][10]; struct Test *(*p)[10] = ar;
【解决方案2】:

来自 C 标准(6.5.2.1 数组下标)

约束

1 表达式之一应具有类型“'指针完成 对象类型'',另一个表达式应该是整数类型,并且 结果的类型为“类型”。

在作业的左侧

p[0][1] = &foo 

o 是由于声明而指向不完整对象类型的指针

struct Test *(*p)[] = &ar;

其中Test *[] 类型是不完整类型,因为数组的大小未知(未指定)。所以编译器会报错。

在此声明中

*(*p+1) = &foo;

在表达式*p + 1 中使用的解引用指针p (*p) 被转换为指向数组ar 的第一个元素的指针,并具有struct Test ** 类型。表达式*p + 1 指向数组的第二个元素,在解除引用 *( *p + 1 ) 后,您将获得数组第二个元素的左值,该元素获取对象 foo 的地址。

在此声明中

(*(*p+1)+1) = &foo;

使用了pointer + 1 类型的右值。所以你不能给这个临时对象赋值。

看起来和这段代码 sn-p 中的一样

int a[] = { 1, 2 };
int *p = &a[0];

p + 1 = &a[1];

【讨论】:

  • 那么这个错了吗? (*(*p+1)+1) = &amp;foo;?如果是这样,那应该如何正确?
  • @Herdsman 这没有意义。表达式 *( *p + 1 ) 产生数组的第二个元素。它的值设置为 &foo。现在您正在获取对象 foo 之后的内存地址,并尝试将其设置为 &foo。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-22
  • 2014-11-19
  • 1970-01-01
  • 1970-01-01
  • 2011-04-08
  • 1970-01-01
相关资源
最近更新 更多