0

我正在解决老师给我的一个问题,但遇到了一个小问题。我应该给出以下代码的输出:(它是用 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的部分

有人可以帮我吗?

4

5 回答 5

5

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

“小”问题:

  • C++ 中输入/输出流的正确标头是<iostream>, 不是<iostream.h>
  • main()返回一个int,而不是一个void
  • coutandendl不能using namespace std;在文件开头没有 a 使用,或者更好:使用std::coutand std::endl

“核心”问题:

  • char* p = "School";是指向字符串字面量的指针。此转换在 C++03 中有效,在 C++11 中已弃用。除此之外,通常字符串文字是只读的,并且尝试修改它们通常会导致段错误(并且修改字符串文字在标准中是未定义的行为)。因此,每次使用时都有未定义的行为p,因为您修改了它指向的内容,即字符串字面量。
  • 更微妙的(和实际的解释):你p在行中修改了几次std::cout<<p<<","<<++(*(p--))<<","<<++(*(p++))<<std::endl;。这是未定义的行为。用于操作的顺序p没有定义,这里似乎编译器从右边开始。您可以查看序列点、之前/之后的序列以获得更好的解释。

您可能对此处的实时代码感兴趣,这更像您对程序的期望。

于 2013-03-14T17:59:39.677 回答
4

假设您正确:

  1. 标题到<iostream>- 没有iostream.h标题
  2. 您分别使用coutand endlwithstd::coutstd::endl
  3. mainto的返回类型int

好的,

char *p = "School";

字符串文字"School"的类型为“array of 7 const char”。转换为char*C++03 中已弃用。在 C++11 中,这是无效的。

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

在这里,我们遇到了未定义的行为。正如我之前所说,char字符串文字中的 s 是const. 您根本无法修改它们。此处的前缀++将尝试修改S字符串文字中的字符。

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

于 2013-03-14T17:54:56.310 回答
3

即使前面的行是合法的,这行也是未定义的行为,这意味着您无法准确预测输出将是什么:

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

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

于 2013-03-14T18:00:10.663 回答
1

这段代码至少存在三个问题(也许更多;我不是 C++ 专家)。

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

第二个问题是它在没有声明的情况下使用coutendl来自命名空间。std您应该为他们的访问添加前缀std::或添加using namespace std;声明。

第三个问题是第二行上的操作发生的顺序cout是未定义的行为,导致字符串在第一行末尾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,chooldiool,i,d。)

它仍然有未定义的行为。cout要解决此问题,请按如下方式修改第二行:

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

那应该给出T,chool, chool,d,U(假设一个字符集按顺序从 A 到 Z)。

于 2013-03-14T18:09:08.330 回答
0
  1. p++ 将 p 的位置从“学校”移动到“学校”。在此之前,因为它是 p++,而不是 ++p,所以它增加了 char 的值。现在 c = "T" 从 "S"
  2. 当您输出 p 时,您会输出 p 的其余部分,我们之前将其标识为“chool”。
  3. 由于最好从反复试验中学习,因此请使用调试器运行此代码。这是一个伟大的工具,将永远跟随你。这将有助于第二组 cout 语句。如果您需要有关 gdb 或 VS 调试器的帮助,我们可以逐步完成。
于 2013-03-14T17:47:44.720 回答