【问题标题】:Why do strings work, but character and int arrays do not work in a pointer array?为什么字符串可以工作,而字符和 int 数组在指针数组中不起作用?
【发布时间】:2021-12-04 15:14:04
【问题描述】:

我知道如果我添加数组 st 和 st2 以在内存中为其提供空间,然后将其添加到指针数组中,这应该不是问题:

/* works */
int st[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int st2[]= {0,31,29,31,30,31,30,31,31,30,31,30,31};
int *day_tab[]= {
        st,
        st2
};

但是如果没有先在内存中给它空间,为什么字符串特别有效? 下面的代码给出了一个错误:

int *day_tab[]= {
        {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}
};

下面的代码也是这样:

char *day_tab[]= {
        {'0','1','\0'},
        {'0','1','\0'}
};

但下面的代码有效

char *day_tab[]= {
        "01",
        "01"
};

【问题讨论】:

  • “我明白如果我添加数组以在内存中给它空间” - “添加数组”是什么意思?
  • 让我编辑问题
  • "0" 是一个具有静态存储持续时间的数组。括号列表不是任何类型的对象(它们只为您正在初始化的任何内容提供初始值)
  • 再次编辑。谢谢@MM。如果可能,请您详细说明。
  • @hamzasiddiq 你还没有解释“添加数组”是什么意思。

标签: arrays c string pointers character


【解决方案1】:

这个

int st[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int st2[]= {0,31,29,31,30,31,30,31,31,30,31,30,31};
int *day_tab[]= {
        st,
        st2
};

是三个数组:两个整数(有自己的存储空间),一个由两个元素组成的数组,它们是指向前两个数组的指针。

但是,这是无效的:

int *day_tab[]= {
        {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}
};

和之前一样,您已经声明了一个指向整数的指针数组,但是指向什么的指针呢?那些花括号列表不是存储位置,它们不能被指向。

你的最后一个例子基本上是有效的,但很危险:

char *day_tab[]= {
        "01",
        "01"
};

它是一个由两个指向字符的指针组成的数组,这些指针用字符串字面量初始化。字符串文字非常特殊,因为它们实际上存储在某个地方,通常在只读内存中,并且它们可以共享(因此使用两次的“01”字符串可以只存储一次)。大括号列表在 C 中没有此功能,它仅适用于字符串文字。

最终代码危险的原因是它是char* 而不是const char*。出于向后兼容性的原因,接受非常量类型,但这不是一个好主意,因为不允许修改文字字符串中的数据。因此,如果您实际使用这些指针写入“01”字符串存储,那么您将面临潜在的灾难。

【讨论】:

    【解决方案2】:

    以下作品

    int *day_tab[]= {
            st,
            st2
    };
    

    因为当你访问一个数组时,它被转换为一个指向第一个元素的指针(这个规则很少有exceptions)。因此,当您在初始化中使用stst2 数组时,它们将转换为指向相应数组的第一个元素的指针,并且在初始化后,指针day_tab[0] 将指向数组st 的第一个元素和指针@987654328 @ 将指向数组st1 的第一个元素。

    在代码sn-p中

    int *day_tab[]= {
            {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}
    };
    

    char *day_tab[]= {
            {'0','1','\0'},
            {'0','1','\0'}
    };
    

    您正在尝试使用多个初始化程序初始化数组day_tab 的指针。请注意,指针是标量类型,来自 C11 Standard#6.7.9p11

    11 标量的初始值设定项应为单个表达式,可选用大括号括起来......

    但是,您可以使用compound literal 来初始化day_tab int 指针数组的指针,如下所示:

        int *day_tab[]= {
            (int []){0,31,28,31,30,31,30,31,31,30,31,30,31},
            (int []){0,31,29,31,30,31,30,31,31,30,31,30,31}
        };
    

    这将初始化指针day_tab[0]day_tab[1] 以指向各自数组的第一个元素。 同样,对于char指针数组,你可以这样做

        char *day_tab[]= {
            (char []){'0','1','\0'},
            (char []){'0','1','\0'}
        };
    

    当你这样做时

    char *day_tab[]= {
            "01",
            "01"
    };
    

    它之所以有效,是因为字符串文字是字符数组,当它在表达式中使用时,它将转换为指向类型 char 的指针,该指针指向数组的第一个元素。因此,这会初始化指针 day_tab[0]day_tab[1] 以指向 只读 字符串文字 "01" 的第一个元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-07
      • 2016-06-27
      • 2017-09-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多