Search code examples
cpointersdeclarationdereference

C cannot declare valid int pointer


I'm working on a program to get the day of the year to its equivalent day and month. For example, day 60 of year 1988 corresponds to the 29th of the 2nd month (February).

The function uses int pointers to assign the resultant month and day:

void month_day(int year, int yearday, int *pmonth, int *pday);

I'm running across a weird error, getting a segmentation fault error. After debugging, I've seen that the problem is with *pday. Despite defining it, C is somehow unable to fetch a valid adress (it assigns adress 0x0) so I get a segmentation error when trying to assign to pointer's adress:

int main() {
int *pmonth, *pday;
month_day(1988, 60, pmonth, pday);
}

void month_day(int year, int yearday, int *pmonth, int *pday) {
  /* some calculations on yearday */
  
  /* Error takes place here because `pday` isn't a valid adress */
  *pday = yearday;
}

I have been able to overcome this issue by defining an int instead of a pointer and passing its address to the function instead of a pointer, as in:

int *pmonth, pday;
month_day(1988, 60, pmonth, &pday);

Somehow the problem is only with the 2nd pointer and as I said, it happens because pointer *pday is assigned an invalid adress after its definition.

However, I really cannot explain why does the error takes place in the first place.

Could someone please explain me why does this happen?

In case it's necessary, the complete code is here:

#include <stdio.h>


void month_day(int year, int yearday, int *pmonth, int *pday);

int main() {
  int *pmonth, *pday;
  month_day(1988, 60, pmonth, pday);
  printf("%d %d\n", *pmonth, *pday);
}

static char arrnonleap[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static char arrleap[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static char *daytab[] = {arrnonleap, arrleap};

/* month_day: set month, day from day of year */
void month_day(int year, int yearday, int *pmonth, int *pday) {
  int i, leap;

  if (year < 0 || yearday < 0 || yearday > 366)
    printf("Invalid year and/or yearday\n");
  
  leap = year%4 == 0 && year%100 != 0 || year%400 == 0;
  for (i = 1; yearday > (*(daytab + leap))[i]; i++)
    yearday -= (*(daytab + leap))[i];
  *pmonth = i;
  *pday = yearday;
}

Solution

  • int main(void) {
      int *pmonth, *pday;
      month_day(1988, 60, pmonth, pday);
      printf("%d %d\n", *pmonth, *pday);
    }
    

    you need to initialize the pointer with valid memory location big enough to accommodate the int

    int main(void) {
      int month,day;
      int *pmonth = &month, *pday = &day;
      month_day(1988, 60, pmonth, pday);
      printf("%d %d\n", *pmonth, *pday);
    }
    

    or just simple

    int main(void) {
      int month, day;
      month_day(1988, 60, &month, &day);
      printf("%d %d\n", month, day);
    }
    
    int main(void) {
      int *pmonth = malloc(sizeof(*pmonth)), *pday = = malloc(sizeof(*pday));
      month_day(1988, 60, pmonth, pday);
      printf("%d %d\n", *pmonth, *pday);
      free(pmonth);
      free(pday);
    }