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已经抛出不兼容的指针赋值警告)。由于指针不兼容,我知道警告。
答案 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。