Почему отображается «Неверное преобразование типов»? - PullRequest
1 голос
/ 07 ноября 2019

У меня есть этот кусок кода C (для платформ MSP430, cl430 компилятор):

void function(uint8_t * x){
    // This variable is defined in the linker file as "X_ADDR = 0xE000;"
    extern uint32_t X_ADDR; 
    uint16_t i = 0;
    uint16_t size = 10;
    uint32_t dst_addr = (uint32_t) &X_ADDR; 

    for (i=0; i < size; i++){
         *((uint8_t *) (dst_addr+i)) = *(x+i); // <-- This line shows the warning
}

Я понимаю, что это так, но вот где я, наверное, ошибаюсь:

*((uint8_t *) (dst_addr+i)) = *(x + i);
                |       |       |   |
                V       V       V   V
*((uint8_t *) (u32  + u16)) = *(u8*+u16);
       *((uint8_t *) (u32)) = *(u8*);
                     *(u8*) = u8;
                         u8 = u8;

Эта платформа 16-разрядная, но она поддерживает расширенный режим адресации 20-разрядных.

Есть ли намеки на это? и как это сделать вместо этого? Заранее спасибо

Ответы [ 3 ]

3 голосов
/ 07 ноября 2019

Вы, кажется, получаете это на 64-битных компиляторах, которые используют 64-битные указатели. Преобразование 32-разрядного целого числа в 64-разрядный указатель сомнительно и непереносимо.

Исправьте это, используя переносимый целочисленный тип, предназначенный для этой цели:

uintptr_t dst_addr = 0x00FFABCD; 

Теперьон будет аккуратно скомпилирован на всех основных 64-битных компиляторах. Пробовал на gcc, clang icc с -std=c11 -Wextra -Wall -pedantic-errors, без проблем.

Кроме того, при доступе к абсолютному адресу вам почти наверняка понадобится volatile квалифицировать указатель.

0 голосов
/ 07 ноября 2019

Вы конвертируете 32-разрядное целое число в 16-разрядный указатель.

Чтобы гарантировать, что ваш целочисленный тип имеет тот же размер, что и указатель, используйте uintptr_t из <stdint.h>.


И когда вы рассматриваете X_ADDR как байтовый массив, было бы лучше объявить его так:

extern uint8_t X_ADDR[];

X_ADDR[i] = ...;
0 голосов
/ 07 ноября 2019

Он возражает против преобразования целого числа dst_addr в указатель, а не присвоения uint8_t

$ gcc -c -Wall -W type.c
type.c: In function 'function':
type.c:11:12: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
          *((uint8_t *) (dst_addr+i)) = *(x+i); // <-- This line shows the warning
            ^

, и clang предлагает аналогичные:

$ clang -c type.c -W -Wall
type.c:11:12: warning: cast to 'uint8_t *' (aka 'unsigned char *') from smaller integer type 'unsigned int'
      [-Wint-to-pointer-cast]
         *((uint8_t *) (dst_addr+i)) = *(x+i); // <-- This line shows the warning
           ^

(clang 3.4.2; gcc 4.8.5)

Преобразование из int в указатель всегда подозрительно, и я не уверен, что есть способ сказать компилятору, что вы действительно это имели в виду, по крайней мере, если вывключите все предупреждения (что является хорошей практикой).

...