2013-07-25 80 views
2

下面是我想知道旁边注释中2个问题的答案的代码。请帮我C++中的字符串和指针

#include<iostream> 

using namespace std; 

int main() 
{ 
    char *p="Hello"; 
    cout <<*p;  //gives H 
    cout <<*(p++); //also gives H.Why? 
    cout <<*(p++); //gives e. 
    cout <<*(p++); //gives l. 
    cout <<*(p++); //gives l. 
    cout <<*(p++); //gives o. 
    cout <<*(p++); //gives no output.Why? It should give some garbage value! 
} 
+0

使'const char *',而不是'char *'。 – chris

+0

@chris:这是一个不同的问题。我想了解当前代码的奇怪输出。 –

+0

p ++表示后增量,取第一个值,然后递增 –

回答

3

p ++所做的是递增p并返回p的旧值,因此*(p ++)将始终返回存储在* p处的字符,并且在语句* p将指向下一个字符之后。

cout <<*(p++); //gives 0. 

这实际上并没有给0,它使字符“o”,在Hello的最后一个字符。

cout <<*(p++); //gives no output.Why? It should give some garbage value! 

这将输出终止字符串的NUL字符。这是一个不可打印的字符,并且您看到此输出的位置,您可能看不到任何可能的原因,因为该软件决定不打印非printable。如果你看一下输出例如十六进制转储,你可以看到NUL右后○:

00000000 48 48 65 6c 6c 6f 00        |HHello.| 

如果添加另一个cout <<*(p++)威力看到垃圾输出,或者该程序可能会崩溃,或者可能会发生其他事情,因为这会是“未定义的行为”。

+0

:感谢您的支持Sir.How我可以看到十六进制转储?我正在使用linux与g ++。 –

+0

像下面这样将程序的输出输出到'hd'或'hexdump -C':'programname | hexdump -C' – Joni

+0

这些'00000000'在开始处表示什么? –

4

*(p++)'h',因为你首先要问的价值比增加你的指针的位置,并在最后一行同样的事情。

+0

但是不会执行第一个p ++',因为它在括号内 –

+0

Postfix op返回原始值。前缀返回增加 – Borgleader

+0

否在该点的值被赋予操作后完成增量 – Engine

3

p++实际上请求值,然后增加它。如果你想增加它,然后增加值,使用++p

对于你的最后一个问题,C字符串的最后一个值始终为'\0'。在大多数情况下,在终端上不会打印任何内容,但这是C++标准未定义的行为。

+1

“'\ 0”。终端上没有任何内容。“ - 我们被告知Insane编码器就是这种情况,但行为不是由C++标准定义的,它不打印任何东西不应该被依赖。 –

+0

@TonyD感谢精度,我编辑了答案 –

4
  1. 如果你在代码中使用p++任何地方,说:

    <some code> p++ <some code> 
    

    这相当于

    <some code> p <some code>; 
    p = p + 1; 
    

    相反,如果你写:

    <some code> ++p <some code> 
    

    这是相当于

    p = p + 1; 
    <some code> p <some code> 
    

    这应该回答你的第一个问题。

  2. C风格的字符串自动以\ 0字符结尾。所以,如果你声明:

    char *p="Hello"; 
    

    ,编译器会自动添加一个\ 0到该字符串为您的结束(否则如printf函数不会知道,当字符串结束)。所以,你的字符串实际上是:

    "Hello\0" 
    

    如果你尝试,虽然推指针进一步,你会在无效的内存结束了,你可能会遇到的任何东西(垃圾,这可能是一系列的零和)

+1

这里没有未定义的行为。 “Hello”的第六个字符是“\ 0”,每次都有保证。 –

+0

我低估了,因为你错了。 “你好”的第六个字符是''\ 0''。没有什么不明确的。 –

+0

@LeeDanielCrocker我被OP的'cout << *(p ++)误导了; //给0'(而不是'//给o')。事实上,他仍然在有效的记忆中。我的错。编辑答案。 – Spook

1

第一个*(p++)给出“H”,因为++运算符被定义为首先给出其当前值,然后执行增量。最后的*(p++)返回字符'\0',因为字符串文字"Hello"指向一个包含SIX字符的数组,最后一个字符是'\0'

0

这样做:

{ 
    char *p="Hello"; 
    cout <<*p;  //gives H. 
    cout <<*(++p); //gives e. 
    cout <<*(++p); //gives l. 
    cout <<*(++p); //gives l. 
    cout <<*(++p); //gives o. 
    cout <<*(++p); //gives 0. 
    cout <<*(++p); //will either be a garbage value or throw an exception 
} 

该++则p递增指针,然后返回值。 p ++将值推入堆栈,增加指针并弹出堆栈以返回它。它也可能使用寄存器;实现细节是编译器的一种。

1

这是因为当使用后增量(例如您的p++)时,在之前,增量完成后评估值为

因此,在你的代码,你的第一个cout << *(p++);将打印“H”,因为它会之前评估的p价值的分配,这是p的地址,然后的p值递增。

要在评估之前递增p的值,请使用增量前++p

因此,这是在你的代码会发生什么:

int main() 
{ 
    char *p="Hello"; 
    cout <<*p;  //gives H 
    cout <<*(++p); //this time it will give e 
    cout <<*(++p); //gives l. 
    cout <<*(++p); //gives l. 
    cout <<*(++p); //gives o. 
    cout <<*(++p); //gives no output since the character after a string is always \0 (credit to answer below) 
} 

希望这有助于! = D

+1

它不应该给垃圾。它给出了''\ 0',因为所有的字符串都以'\ 0'结尾。 – Rapptz

0
char *p="Hello"; 
cout <<*p;  //gives H 
cout <<*(p++); //also gives H.Why? 

因为后评估会在评估后增加p。 要增加p前评估,使用*(++p)

cout <<*(p++); //gives e. 
cout <<*(p++); //gives l. 
cout <<*(p++); //gives l. 
cout <<*(p++); //gives 0. 
cout <<*(p++); //gives no output.Why? It should give some garbage value! 

有一个填充\0在每一个C风格的字符串。