Ошибка [Pe142]: выражение должно иметь тип указателя на объект

#c #embedded #iar

#c #встроенный #iar

Вопрос:

Я кодирую c в IAR Embedded workbench IDE. У меня есть следующее в заголовочном файле.

 typedef union {
uint8_t payload;
struct UBX_NAV_POSLLH  nav_posllh;
struct UBX_NAV_STATUS  nav_status;
struct UBX_NAV_DOP     nav_dop;
struct UBX_NAV_SOL     nav_sol;
struct UBX_NAV_VELNED  nav_velned; 
struct UBX_NAV_TIMEUTC nav_timeutc;
struct UBX_NAV_SVINFO  nav_svinfo;
} UBXPayload;

struct UBXHeader {
uint8_t  class;
uint8_t  id;
uint16_t len;
uint8_t  ck_a;
uint8_t  ck_b;
};

struct UBXPacket {
struct UBXHeader header;
UBXPayload payload;
};
  

Вот мой исходный файл:

 static char *c_buffer
void myinit( )
{
  c_buffer= (char*)malloc(50);
}
int myfunc(uint8_t c, char *c_buffer)
{
  static uint8_t rx_count = 0;
  struct UBXPacket *ubx   = (struct UBXPacket *)c_buffer;
  for(int i=0; i<3; i  ){        
    ubx->payload.payload[rx_count] = c; /* Error[Pe142]: expression must have pointer-  to-object type */
    rx_count  ;
   }
}

void main( )
{
  char mychar = 'h';
  myinit( );
  myfunc(mychar,  c_buffer);
}
  

То же самое объединение определено следующим образом в другом примере кода, написанном для компиляции с помощью компилятора ARM GCC. Оно хорошо компилируется и хорошо работает.

 typedef union {
uint8_t payload[0];  /* here [0] is placed */
struct UBX_NAV_POSLLH  nav_posllh;
struct UBX_NAV_STATUS  nav_status;
struct UBX_NAV_DOP     nav_dop;
struct UBX_NAV_SOL     nav_sol;
struct UBX_NAV_VELNED  nav_velned; 
struct UBX_NAV_TIMEUTC nav_timeutc;
struct UBX_NAV_SVINFO  nav_svinfo;
} UBXPayload;
  

Но в компиляторе IAR C выдается ошибка. Пожалуйста, какие-либо предложения?
Я не понимаю следующую строку

 struct UBXPacket *ubx   = (struct UBXPacket *)c_buffer;
  

Комментарии:

1. Как свидетельствуют ваши комментарии к ответам, этот вопрос не совсем точен. Похоже, вы изменили объединение из исходного кода; исходный код компилируется в GCC, но этот код не будет работать в любом компиляторе. Вы должны подробно описать свое изменение — или лучше, просто спросите об исходной проблеме, а не о своем ошибочном решении.

Ответ №1:

В UBXPayload объединении payload членом является один символ, но вы используете его как массив. И когда вы превращаете его в массив, вы превращаете его в массив нулевого размера, поэтому все записи в массив будут выходить за рамки, что приведет к неопределенному поведению (так что это работает не так хорошо, как вы думаете).

Комментарии:

1. Спасибо за ответ. Я не понимаю, почему подобный код компилируется в компиляторе GCC. в чем разница? Как исправить эту ошибку.

2. @Armfan Вы исправляете ошибку, создавая payload ненулевой массив. Либо это действительно делает его указателем и динамически (повторно) распределяет при необходимости. И нет, если это не массив, ни один компилятор (даже GCC) не будет его компилировать.

3. Вы не возражаете, если я попрошу вас обратиться к некоторому коду по следующей ссылке. Номер строки 97. reviews.openpilot.org/browse /~br=next/OpenPilot/полет /модули/… Я не понимаю, как это работает.

4. @Armfan : В этом случае элемент полезной нагрузки определяется в ubx.h как «массив нулевой длины» таким образом uint8_t payload[0]; . Массивы нулевой длины являются расширением GCC . В этом случае вы можете безопасно определить его как uint8_t payload[1]; , поскольку все остальные члены в любом случае длиннее 1 байта. Однако, если вы получаете доступ через payload за пределами заявленных границ, некоторые инструменты статического анализа или анализа во время выполнения могут выдать предупреждение.

5. @Armfan — Я не запутался — мне совершенно ясно, что IAR в этом отношении соответствует ISO, а GCC — нет. Использование payload[1] — это решение, и любые проблемы, которые оно вызывает, вероятно, легче решить, чем недопустимый код , который не будет компилироваться ! Если вы не будете откровенны с проблемами, которые это вызывает, вам больше не смогут помочь. Возможно, следует опубликовать новый вопрос о новой проблеме.