【问题标题】:const char **a = {"string1","string2"} and pointer arithameticconst char **a = {"string1","string2"} 和指针算术
【发布时间】:2015-02-08 14:11:01
【问题描述】:
main()
 {
     const char **a = {"string1","string2"};
     printf("%c", *a); /* prints s */
     printf("%s", a);  /* prints string1 */
     printf("%s", a+1);/* prints ng1 */
 }

GCC v4.8.3 为最后一个 printf 打印“%s”,而 http://codepad.org/ 打印“ng1”。

我认为代码将创建一个指向两个字符串的指针数组,并将基地址分配给 a,这允许正常的指针运算。但似乎假设有问题。第一个 printf 表明我的假设是错误的。谁能解释为什么会观察到这种行为? (请注意,VS 2012 抛出了一个错误,指出太多初始化器,而 GCC 抛出了不兼容指针分配的警告)。由于指针分配不兼容,我知道警告。

【问题讨论】:

  • const char **a = {"string1","string2"}; 是错误的。您的 main() 不返回 int 这也是错误的。在假设你写的东西应该可以工作之前,请阅读指针和数组。
  • 问题不是关于我的程序的绝对正确性,请注意这是一个由 GCC v4.8.3 编译的合法程序,带有警告。问题是关于为什么这种行为很奇怪。
  • @bare_metal 这不是一个合法的程序。 gcc 的处理方式并没有改变这一事实

标签: c pointers


【解决方案1】:

const char **a 不是指向两个字符串的指针数组。它将a 声明为指向const char 的指针。

const char **a = {"string1","string2"}; //No memory is allocated to store string literals 

将调用未定义的行为,您可能会得到预期或意外的结果。
要将 a 声明为两个指针的数组,您需要将声明更改为

const char *a[] = {"string1","string2"};

【讨论】:

  • 我知道这一点,但请您帮我理解为什么程序会这样运行。如果我创建一个指针数组,然后将其转换回 char**,那么事情会按预期工作
  • 怎么说内存没有分配,在char* a = "string1"里面string存储在.rodata里?
  • @bare_metal;你认为char* achar** a 是一样的吗?
  • 我不这么认为,但我确实认为 char* a = "string" 和 char **a = {"string1","string2"};必须将它们存储在某个地方并打印确认它已存储。
  • @bare_metal;您需要在pointers and arrays 上阅读更多内容。
【解决方案2】:

你的程序栈中的内存范围是这样的:(注意它在赋值之前没有分配,这是错误的)

char** a = {s, t, r, i, n ,g, 1, \0, s, t, r, i, n, g, 2, \0}

因此当你打印命令时:

printf("%c", *a);

您正在取消引用字符串的第一个字符“s”。

另一方面,当你打印命令时:

 printf("%s", a);

您正在打印一个从指针 a 开始并在 '\0' 结束的字符串。这就是您看到输出“string1”的原因。

最后,当您键入“a+1”时,您会一步增加指针(此处示例:How to increment a pointer address and pointer's value?)。在这种情况下,因为 char** 是一个指针,并且每个指针都是 4 个字节,所以“+1”向前跳转了 4 个字符。 因此,当您打印命令时:

printf("%s", a+1);

printf 从指针 'a' + 4 个字节开始,到 '\0' 结束。这就是输出为“ng1”的原因。

希望它足够清楚。

【讨论】:

  • 感谢您的尝试,但解释似乎有误
  • 请详细说明。你认为到底哪里错了?如果需要,我很乐意编辑我的答案。
  • const char a = {"string1","string2"};和 const char a = {s, t, r, i, n ,g, 1, \0, s, t, r, i, n, g, 2, \0} 不一样(''被省略),当我尝试 printf("%s", a);我遇到了段错误。
  • 那你为什么在输入 printf("%s",a); //打印string1?
  • 显然我不是说 a = {s, t, r, i, n ,g, 1, \0, s, t, r, i, n, g, 2, \ 0}。我的意思是以“a”开头的内存范围如下所示。没关系。很高兴你知道了。
【解决方案3】:

这是由于 GCC 执行了以下特殊初始化。 请参阅int q = {1,2}; peculiar initialization list。语句 const char **a = {"string1","string2"};导致 a 被视为 const char **a = "string1"。这解决了*a会打印's'的谜团,a会打印string1。

【讨论】:

    猜你喜欢
    • 2011-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多