C 程序因指针赋值而崩溃

C program crashes because of pointer assignment

我正在为 ANSI C 书中的一个练习编写程序,当我到达这一行时程序崩溃了:

*pmonth = i;

函数 month_day.

#include <stdio.h>

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

int main(int argc, char *argv[]){
    int year = 1994;
    int *month;
    int yearday = 288;
    int *day;
    month_day(year, yearday, month, day);
    printf("Month = %d, day = %d", *month, *day);
    return 1;
}

static char daytab[2][14] = {
        {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
        {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

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

    leap = (year%4 == 0 && year%100 != 0) || year%400 == 0;
    char *p = &daytab[leap][1];
    for(i = 1; yearday> (int) *p; i++){
        yearday -= *p++;
    }
    *pmonth = i; /*CRASHES HERE*/
    *pday = yearday;
}

知道为什么会这样吗?我对指针比较陌生,所以我很容易犯一个愚蠢的错误。提前致谢。

编辑谢谢你们的回答和耐心,试图掌握指点。

指针pmonth没有初始化。所以你不应该取消引用它。您应该为指针分配一个有效地址。为此,您可以使用 & 运算符分配一个变量地址或调用 malloc(1).

因为你的主函数似乎不需要指针,你的代码应该是:

int main(int argc, char *argv[]){
    int year = 1994;
    int month;
    int yearday = 288;
    int day;
    month_day(year, yearday, &month, &day);
    printf("Month = %d, day = %d", month, day);
    return 1;
}

在这段代码中,我们给pmonthpday变量monthday的地址。这些变量存在于此上下文中,因此它们的地址是有效的。这样,pmonthpday 指向有效内存。

如果您的主函数中确实需要指针,请调用 malloc(1) 为您的程序分配内存并将此内存块的地址存储到您的指针中。

这是因为您从未为 pmonth 创建任何指向的内存。您需要将任何指针指向某个内存以便它进行编辑,如果您不这样做并且指针未初始化或 NULL 那么您有 未定义的行为 。未定义的行为意味着任何事情都可能发生,包括程序崩溃或偷你的车。

像这样就足够了:

int month; // Some actual memory.
int *pmonth = &month; // pmonth now points to something real.

不过话又说回来,month_day函数的重点是提供输出参数,所以即使这样也足够了:

int month, day;

month_day( ..., &month, &day)

永远不要使用未初始化的指针或取消引用空指针,你所做的是未定义的行为,世界上任何事情都可能发生。

您定义了一个函数 void month_day(int year, int yearday, int *pmonth, int *pday),它需要将两个指向 int (pmonth and pday) 的指针传递给它。您已将指针正确传递给 int 并且编译器已成功编译您的程序,但这些指针未指向正确的内存地址。当您访问未初始化的指针(可能无效或不属于您)指向的地址时,您会得到 Segmentation Fault

段错误是由于访问“不属于你”的内存而导致的一种特定错误。这是一种辅助机制,可防止您破坏内存并引入难以调试的内存错误。

有很多方法可以得到段错误。获得段错误的常见方法是取消引用空指针:

int *p = NULL;
*p = 1;

要解决您的问题,您的代码应该如下所示

int main(int argc, char *argv[])
{
    int year = 1994;
    int month;
    int yearday = 288;
    int day;

    month_day(year, yearday, &month, &day);
    printf("Month = %d, day = %d", month, day);

    return 0;
}

您可以调用malloc函数来动态分配内存,并将malloc函数返回的地址分配给您的指针变量。 Remember, to call free function to release memory allocated dynamically when you no longer need the memory.