【问题标题】:'C' Segmentation fault with 2d array'C' 二维数组的分段错误
【发布时间】:2014-10-12 17:18:08
【问题描述】:

谁能解释一下为什么这段代码不起作用?

#include <stdio.h>
#include <stdlib.h>

void findAndPrint(char *arr[], int year, int month, int day);

int main()
{
    char *dayTab[] = {
        {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
        {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    };
    findAndPrint(dayTab, 3, 3, 3);
    getchar();
    return 0;
}

void findAndPrint(char *arr[], int year, int month, int day ){
    int d = 0;
    if(month > 12 || month < 1 || day > 31 || day<1)
        return;
    int leap = ((year%4==0 && year%100!=0) || year%400 == 0)?1:0;
    int i;
    for(i=0; i<month-1; i++){
        d += arr[leap][i];
    }
    d+= day;
    printf("Day = %d", d);
}

IDE(Code::Blocks) 写入“程序收到信号 SIGSEGV。分段错误。”

【问题讨论】:

  • 编译器不知道函数findAndPrint内部char *arr[]的尺寸。要么将它作为char arr[][12] 传递(或者如果你真的想要,作为char [2][12]),或者简单地在函数中声明它,因为它似乎是逻辑上正确的地方。另外,如果您打算多次调用它,请声明它static,以避免每次调用时都初始化。
  • void findAndPrint(char arr[][12], int year, int month, int day); , char dayTab[][12] = {
  • 你真的应该关心编译器发出的警告。他们不是为了好玩......
  • @BLUEPIXY 我在 'findAndPrint' 函数中声明了它,但 IDE 写的是一样的。
  • @user3051029:那是什么语言?您的 dayTab 声明在 C 中甚至都不是远程有效的。没有兼容的 C 编译器会接受它。您正在为只有一层聚合嵌套的数据结构打开第二层嵌套 {}

标签: c arrays codeblocks segmentation-fault


【解决方案1】:

首先你需要一个二维字符数组,不是一个字符指针数组。

char dayTab[][12] = {
    {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

然后你必须更改函数以接受该类型。

void findAndPrint(char arr[][12], int year, int month, int day ) ;

其余的看起来还可以。

尝试使用参数:

findAndPrint(dayTab, 2014, 10, 12);

给我们一天:285

这是正确的,耶!

【讨论】:

  • 据我所知,我可以将此数组创建为字符指针数组
  • 只要使用正确的初始化语法,代码就可以完美地使用指针数组(如原始帖子中所示)。原始代码的唯一问题是初始化损坏。
【解决方案2】:

如果我正确理解您的意图,您希望那些嵌套的 {31, 28, ... } 序列用作 char[] 数组,上层数组中的指针将指向该数组。

尽管其他答案说明了什么,但说您一定需要文字二维数组是不正确的(即使在这种情况下,二维数组可能比您尝试做的更好)。只要您使用正确的语法,您最初的尝试也将起作用。

现在,您不能只在代码中间植入{31, 28, ... } 序列并期望编译器将其解释为数组。该语言没有这样的功能,但它有一个类似的功能,但语法略有不同。以“内联”方式正确初始化 char *dayTab[] 数组的唯一方法是使用 compound literal 功能。初始化将如下所示

char *dayTab[] = {
    (char []) { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
    (char []) { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};

注意额外的(char []) 语法。这是绝对必要的。这是您必须更改原始代码以使其按预期编译的唯一内容。

您当前在原始代码中的内容不是有效的 C。如果某些编译器接受了此代码(CodeBlocks 中的 GCC?),那么只是由于某些编译器扩展。在这种特殊情况下,那个编译器扩展碰巧对你开了一个残酷的玩笑。我什至不知道它是如何被编译器解释的,但绝对不知道你打算如何解释它。

附:在我的实验中,GCC 给出了一堵诊断信息墙来响应我们的原始代码。你有没有从你的编译器那里得到这些信息?你只是忽略了他们吗?

【讨论】:

    猜你喜欢
    • 2016-05-07
    • 2019-08-03
    • 2015-11-11
    • 1970-01-01
    • 2019-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-15
    相关资源
    最近更新 更多