Делает указатель из целого числа без приведения... DS1307, RTC, BCD

Я знаю, что этот вопрос уже задавался. Это все в Google и на этом сайте, но я не могу понять людей, когда они это объясняют. Я уже потратил слишком много часов, пытаясь понять, и я до сих пор не понимаю, пожалуйста, постарайтесь понять, что есть нечто фундаментальное, чего я НЕ понимаю... вот и все.

При программировании на C на Proteus я часто получаю предупреждение и / или ошибку (в данном случае предупреждение):

makes pointer from integer without a cast

и я не понимаю Как я уже сказал, я уже часами смотрю на это, и я понимаю, что это связано с типами и / или указателями, бла. Кто-нибудь, пожалуйста, объясните мне, как нормальный человек.

Кроме того, я получаю это много. Возможно ли получить это предупреждение от других типов переменных без приведения? Характер? Как бы я решил исправить эту проблему сейчас и избежать ее в будущем?

Вот контекст...

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "stdlib.h"
#include "USART.h"
#include "I2C.h"
#include "ds1307.h"

void Wait()
{
   uint8_t i;
   for(i=0;i<20;i++)
      _delay_loop_2(0);
}

uint8_t ss,mm,hh,dd,nn,yy,x;    // Appropriately labeled variables
uint16_t sec[3],min[3],hr[3],day[3],month[3],year[3],mode[2];
uint16_t secs,mins,hrs,days,months,years,modes;

int main(void)
{
   _delay_ms(50);
   USART_interrupt_init();          // 
   USART_send('\r');                // Send carriage return
   _delay_ms(100);              // Allows for the LCD module to initialize

   I2CInit();                   // Initialize i2c Bus
   DS1307Write(0x07,0x10);          // Blink output at 1Hz
   while(1)
      {
     int i=0;
     /* SECONDS */
     DS1307Read(0x00,&ss);      // Read seconds address
     /* MINUTES */
     DS1307Read(0x01,&mm);      // Read minutes address
     /* HOURS */
     DS1307Read(0x02,&hh);      // Read hours address
     /* DAY */
     DS1307Read(0x04,&dd);      // Read hours address
     /* MONTH */
     DS1307Read(0x05,&nn);      // Read hours address
     /* YEAR */
     DS1307Read(0x06,&yy);      // Read hours address
     for(i=0;i<5;i++)
     {Wait();i++;}

     sec[0]=(0b00001111 & ss);
     sec[1]=((0b01110000 & ss)>>4);
     sec[2]='\0';
     itoa(sec[0],secs,10);

     USART_putstring(secs); // place string in buffer

и 2 ошибки:

../main.c:59: warning: passing argument 2 of 'itoa' makes pointer from integer without a cast

../main.c:62: warning: passing argument 1 of 'USART_putstring' makes pointer from integer without a cast

4 ответа

Решение

Итак, вот совершенно другой ответ на вопрос, на гораздо более высоком уровне, и чтобы прояснить суть, мы собираемся сделать шаг назад от программирования на C и поговорить о строительстве домов. Мы собираемся дать инструкции людям, строящим дом, но представим, что у нас есть какой-то жесткий, кодифицированный способ сделать это, вроде вызовов функций.

Предположим, пришло время рисовать снаружи дома. Предположим, что есть "функция" paint_the_house() это выглядит так:

paint_the_house(char *main_color, char *trim_color);

Вы решаете, что хотите белую отделку на желтом доме, поэтому вы "звоните"

paint_the_house("white", "yellow");

и художники покорно красят дом в белый с желтой отделкой. Упс! Вы сделали ошибку, и никто не поймал ее, и теперь дом не того цвета.

Предположим, есть другая функция, finish_the_floors() это выглядит так:

finish_the_floors(char *floor_material, char *color)

floor_material Предполагается, что аргументом является строка типа "твёрдая древесина", "ковер", "линолеум" или "плитка". Вы решили, что хотите красный плиточный пол в вашем доме, поэтому вы звоните

finish_the_floors("red", "tile");

Но парень, который устанавливает полы, возвращается и говорит: "Слушай, приятель," красный "- это не материал для пола, а" плитка "- это не цвет, так что ты хочешь попробовать это снова?" На этот раз кто-то поймал вашу ошибку.

Наконец, предположим, что есть функция

furnish_the_bathroom(char *bath_or_shower, int number_of_sinks)

где bath_or_shower предполагается, что это строка "ванна" или "душ", а вторым аргументом должно быть количество желаемых раковин. Вы решаете, что хотите две раковины и ванну, и, продолжая свой небрежный путь, звоните:

furnish_the_bathroom(2, "bathtub");

На этот раз ваш фальшивый "вызов функции" даже не подходит парню, который собирается построить ванну. Племянник дим-лампочки архитектора, которого его брат заключил с ним на работу на лето, который даже не может отличить тостер от двух на четырех, ему поручено передать инструкции от вас до рабочие, и даже он может видеть, что что-то не так. "Хм, подожди минутку", - скулит он. "Я думал, что первая вещь должна была быть строкой, а вторая должна была быть числом?"

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

Ваш компилятор сообщает вам, что функция ожидает указатель, но вы передали целое число. Так что он будет автоматически обрабатывать ваше целочисленное значение как адрес и использовать его как указатель.

Например, itoa ожидает указатель на место в памяти для своего второго параметра - именно там он хранит результирующую строку, которую он строит из целого числа, которое вы передаете. Но вы прошли secs для этого - uint16_t. Компилятор предупреждает вас, что любое значение в этом целом числе будет использоваться как адрес, где itoa помещает полученную строку.

Подобные вещи могут вызвать ошибку на большинстве целей, но я не знаком с Proteus.

Во всяком случае, в качестве примера, чтобы исправить itoa предупреждение, используйте что-то вроде следующего:

char secs[3];
...
itoa(sec[0], secs, 10);

Надеюсь, это поможет.

Это означает, что компилятор неявно приводит его к вам, однако он уведомляет вас об этом, отправляя предупреждение, чтобы вы знали это.

Вот пример использования чисел:

float f = 1.0;
int i = f;

В зависимости от платформы, языка и настроек компилятора возможны несколько сценариев:

  • Компилятор неявно бросает float в int без предупреждения (плохо)
  • то же самое, но выдает предупреждение (лучше)
  • Настройки компилятора изменены, чтобы обрабатывать предупреждения как ошибки (безопасные, критичные для безопасности и т. д.)

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

В вашем конкретном случае я искал USART_pustring и первым, что я нашел, был этот:

void USART_putstring (char * StringPtr)

Не нужно смотреть дальше, передавая int к функции, ожидающей char* (если это так), 'может' привести к неожиданному результату.

Решение

Прочитайте документацию USART_putstring и убедитесь, что вы "преобразовали" свои входные данные в правильный тип, который они принимают, предупреждение исчезнет само по себе.

РЕДАКТИРОВАТЬ:

+1 для Aenimated1

Убедитесь, что вы понимаете, в чем же различия между "целым числом" и "указателем на целое число", он объяснил это довольно хорошо:)

Целые числа для подсчета. Указатели являются абстрактным указанием того, где переменная может быть найдена.

Чтобы держать вещи в голове, лучше не смешивать их, даже если вы работаете в системе, в которой конкретная реализация указателя совпадает с реализацией целого числа.

Преобразование целого числа в указатель или наоборот является ошибкой, если только вы не напишете приведение, говорящее "Я знаю, что я здесь делаю".

К сожалению, некоторые компиляторы выдают "предупреждение", а затем генерируют поддельный двоичный файл. Если возможно, посмотрите, можете ли вы использовать переключатели компилятора, которые заставят компилятор сказать "ошибка" для этого случая.

Если вы видите эту ошибку, это обычно означает, что вы указали целое число, если компилятор ожидал, что вы предоставите указатель.


В своем коде вы делаете это с itoa(sec[0],secs,10); это проблема. itoa подпись функции:

char * itoa ( int value, char * str, int base );

Вы поставили secs, который является uint16_t (16-разрядное целое число) для параметра char * str, Это ошибка, потому что она ожидает адрес объекта, но вы указали номер.


Чтобы это исправить, вам нужно прекратить поставлять целые числа для параметров, которые являются указателями.

Для помощи с тем, как преобразовать вывод DS1307Read к строке отображения, опубликуйте вопрос, спрашивая об этом конкретно.

Другие вопросы по тегам