C 不能声明有效的 int 指针

C cannot declare valid int pointer

我正在开发一个程序,将一年中的某一天换算成对应的日期和月份。例如,1988 年的第 60 天对应于第 2 个月(2 月)的 29 日。

该函数使用 int 指针来分配结果月和日:

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

我 运行 遇到一个奇怪的错误,出现分段错误。调试后,我发现问题出在 *pday。尽管定义了它,但 C 无法以某种方式获取有效地址(它分配地址 0x0),因此在尝试分配给指针的地址时出现分段错误:

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;
}

我已经能够通过定义 int 而不是指针并将其地址传递给函数而不是指针来解决这个问题,如:

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

不知何故,问题只出在第二个指针上,正如我所说,这是因为指针 *pday 在其定义后被分配了一个无效地址。

但是,我真的无法解释为什么首先会发生错误。

有人能解释一下为什么会这样吗?

如果有必要,完整的代码在这里:

#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;
}
int main(void) {
  int *pmonth, *pday;
  month_day(1988, 60, pmonth, pday);
  printf("%d %d\n", *pmonth, *pday);
}

您需要使用足够大的有效内存位置来初始化指针以容纳 int

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

或者只是简单的

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);
}