2 разных странных ошибки с назначением структуры - PullRequest
1 голос
/ 08 мая 2020

Имея этот код:

#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].

EDIT: the same as могут быть ошибочными. Я просто подумал, их было бы одинаково, если бы "нормальные" указатели (их тип)

Ответы [ 2 ]

3 голосов
/ 09 мая 2020

Отвечая на ваши комментарии построчно:

#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 является указателем на что-то неизвестного размера, вам не разрешено использовать на нем арифметику указателя c.

   (*(*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;
}
0 голосов
/ 09 мая 2020

Из стандарта C (6.5.2.1 Индексы массива)

Ограничения

1 Одно из выражений должно иметь тип '' указатель на полный тип объекта '', другое выражение должно иметь целочисленный тип, а результат будет иметь тип '' type ''.

В левой части присваивания

p[0][1] = &foo 

o - указатель на неполный тип объекта из-за объявления

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

, где тип Test *[] является неполным типом, потому что размер массива неизвестен (не указан). Таким образом, компилятор выдает ошибку.

В этом операторе

*(*p+1) = &foo;

разыменованный указатель p (*p), используемый в выражении *p + 1, преобразуется в указатель на первый элемент массива ar и имеет тип struct Test **. Выражение *p + 1 указывает на второй элемент массива, и после разыменования *( *p + 1 ) вы получите lvalue второго элемента массива, который получает адрес объекта foo.

В этом операторе

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

используется rvalue вида pointer + 1. Итак, вы не можете присвоить этому временному объекту значение.

Выглядит так же, как в этом фрагменте кода

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

p + 1 = &a[1];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...