指针递增和递减

时间:2013-03-14 17:40:40

标签: c++ pointers turbo-c++

我正在解决老师给我的一个问题并且遇到了一些问题。 我应该给出以下代码的输出:(用Turbo C ++编写)

#include<iostream.h>
void main()
{
    char *p = "School";
    char c;
    c=++(*(p++));
    cout<<c<<","<<p<<endl;
    cout<<p<<","<<++(*(p--))<<","<<++(*(p++))<<endl;

}

程序提供的输出是:

T,chool
ijool,j,i

我得到指针本身递增的部分,然后递增指针指向值。但我没有得到字符串打印出来的部分 ijool

有人能帮助我吗?

5 个答案:

答案 0 :(得分:5)

您展示的程序是非标准且格式错误(并且不应该编译)。

“小”问题:

  • C ++中输入/输出流的正确标头是<iostream>,而不是<iostream.h>
  • main()返回int,而不是void
  • 如果文件开头没有cout或更好,则无法使用
  • endlusing namespace std;:使用std::coutstd::endl

“核心”问题:

  • char* p = "School";是指向字符串litteral的指针。此转换在C ++ 03中有效,在C ++ 11中已弃用。除此之外,通常字符串litterals是只读的,并且尝试修改它们通常会导致段错误(并且修改字符串litteral是标准的未定义的行为)。因此,每次使用p 时都会有未定义的行为,因为您修改了它指向的内容,即字符串文字。
  • 更精细(以及实际说明):您正在p行中多次修改std::cout<<p<<","<<++(*(p--))<<","<<++(*(p++))<<std::endl;。这是未定义的行为。未定义用于p上的操作的顺序,此处似乎编译器从右侧开始。您可以查看sequence points, sequence before/after以获得更好的解释。

您可能对live code here感兴趣,这更像您对计划的期望。

答案 1 :(得分:4)

我们假设你是正确的:

  1. 标题为<iostream> - 没有iostream.h标题
  2. 您对coutendl分别与std::coutstd::endl的使用
  3. mainint
  4. 的返回类型

    好,

    char *p = "School";
    

    字符串文字"School"的类型为“7 const char的数组。”在C ++ 03中不推荐转换为char*。在C ++ 11中,这是无效的。

    c=++(*(p++));
    

    这里我们点击未定义的行为。正如我之前所说,字符串文字中的charconst。你根本无法修改它们。这里的前缀++将尝试修改字符串文字中的S字符。

    所以从这一点开始,对于应该发生什么进行猜测是没有用的。你有未定义的行为。任何事情都可能发生。

答案 2 :(得分:3)

即使前面的行是合法的,这一行也是未定义的行为,这意味着你无法准确预测输出的内容:

cout<<p<<","<<++(*(p--))<<","<<++(*(p++))<<endl;

注意它是如何在该行上多次修改p的值(实际上是在序列点之间)?这是不允许的。充其量你可以说“在这个运行时库的这个编译器和这个环境的执行时我观察到了以下行为”,但因为它是未定义的行为你不能指望它每次都做同样的事情您运行该程序,或者即使在同一程序运行中多次遇到相同的代码。

答案 3 :(得分:1)

此代码至少存在三个问题(可能更多;我不是C ++专家)。

第一个问题是不应该修改字符串常量,因为它们可以放在程序存储器的只读部分中,OS直接映射到磁盘上的exe文件(操作系统可以在几个运行的实例之间共享它们)例如,相同的程序,或者当RAM很低时,避免需要将这些内存部分写入交换文件,因为它知道它可以从exe获取原始文件。例如,该示例在我的编译器上崩溃。要修改字符串,您应该为字符串分配一个可修改的副本,例如使用strdup

第二个问题是它在cout命名空间中使用endlstd而没有声明。您应该在访问前加std::或添加using namespace std;声明。

第三个问题是第二个cout行上的操作发生的顺序是未定义的行为,导致字符串在第一行结束时显示的时间之间明显神秘的变化{ {1}}行和下一行。

由于此代码不打算特别做任何事情,因此您可以使用不同的有效方法进行修复。这可能会运行:

cout

(在我的编译器上输出:#include <iostream> #include <string.h> #include <stdlib.h> using namespace std; int main() { char *string = strdup("School"); char *p = string; char c; c=++(*(p++)); cout<<c<<","<<p<<endl; cout<<p<<","<<++(*(p--))<<","<<++(*(p++))<<endl; free(string); } T,chool。)

但它仍有未定义的行为。要解决此问题,请按如下方式重新修改第二个diool,i,d行:

cout

这应该给cout << p << ","; cout << ++(*(p--)) << ","; cout << ++(*(p++)) << endl; T,chool(假设一个字符集按顺序包含A到Z)。

答案 4 :(得分:0)

  1. p ++将p的位置从“School”移动到“chool”。在此之前,由于它是p ++,而不是++ p,它会增加char的值。现在c =“T”来自“S”
  2. 输出p时,输出p的余数,我们之前将其识别为“chool”。
  3. 由于最好从试验和错误中学习,因此请使用调试器运行此代码。这是一个永远跟随你的伟大工具。这将有助于第二组cout声明。如果您需要有关gdb或VS调试器的帮助,我们可以完成它。