const char ** a = {" string1"," string2"}和指针arithametic

时间:2015-02-08 14:11:01

标签: c pointers

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,这允许正常的指针算术运算。但似乎这个假设有问题。第一个印刷品表明我的假设是错误的。谁能解释为什么会出现这种行为? (请注意,VS 2012已经抛出一个错误,说太多的initalizers,因为GCC已经抛出不兼容的指针赋值警告)。由于指针不兼容,我知道警告。

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分: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'

希望它足够清楚。

答案 2 :(得分:1)

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