Search code examples
cpointerscastingtype-conversionreal-time-clock

makes pointer from integer without a cast... DS1307, RTC, BCD


I know this question has been asked before. It's all over Google and on this site too, but I can't understand people when they explain it. I have already spent far too many hours trying to understand and I still don't so please try to understand that there's something fundamental I am NOT understanding... here we go.

When programming in C on Proteus, I often get the warning and/or error (in this case warning):

makes pointer from integer without a cast

and I don't get it. Like I said, I've already spent hours looking into it and I get it has to do with types, and/or pointers, blah. Someone please explain it to me like a normal person.

Also, I get this a lot. Could it be possible to get this warning from other types of variables without a cast? A character? How would I go about fixing this problem now, and avoiding it in the future?

Here's the context...

#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

and the 2 errors:

../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

Solution

  • So here's a completely different answer to the question, at a much higher level, and to make the point clear, we're going to take a step back from C programming and talk about building houses. We're going to give instructions to the people building the house, but we're going to imagine we have some rigid, codified way of doing it, sort of like function calls.

    Suppose it's time to paint the outside of the house. Suppose there's a "function" paint_the_house() that looks like this:

    paint_the_house(char *main_color, char *trim_color);
    

    You decide you want white trim on a yellow house, so you "call"

    paint_the_house("white", "yellow");
    

    and the painters dutifully paint the house white with yellow trim. Whoops! You made a mistake, and nobody caught it, and now the house is the wrong color.

    Suppose there's another function, finish_the_floors() that looks like this:

    finish_the_floors(char *floor_material, char *color)
    

    The floor_material argument is supposed to be a string like "hardwood", "carpet", "linoleum", or "tile". You decide you want red tile floors in your house, so you call

    finish_the_floors("red", "tile");
    

    But the guy who installs the floors comes back and says, "Listen, buddy, 'red' is not a floor material, and 'tile' is not a color, so do you want to try that again?" This time, someone caught your mistake.

    Finally, suppose there's a function

    furnish_the_bathroom(char *bath_or_shower, int number_of_sinks)
    

    where bath_or_shower is supposed to be the string "bathtub" or "shower", and the second argument is supposed to be the number of sinks you want. You decide you want two sinks and a bathtub and, continuing your careless ways, you call:

    furnish_the_bathroom(2, "bathtub");
    

    This time, your bogus "function call" doesn't even make it to the guy who's going to build the bathtub. The architect's dim-bulb nephew, who his brother conned him into hiring for the summer, who can't even tell the difference between a toaster oven and a two-by-four, he's been put in charge of relaying instructions from you to the laborers, and even he can see that there's something wrong. "Um, wait a minute," he whines. "I thought the first thing was supposed to be a string, and the second thing was supposed to be a number?"

    And now we can go back to your question, because that's basically what's going on here. When you call a function, you have to pass the right arguments in the right order (just like your instructions to the builders). The compiler can't catch all your mistakes, but it can at least notice that you're doing something impossibly wrong, like passing an int where you're supposed to pass a pointer.