0

I was solving a question my teacher gave me and hit a little snag. I am supposed to give the output of the following code:(It's written in Turbo C++)

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

}

The output the program gives is:

T,chool
ijool,j,i

I got the part where the pointer itself increments and then increments the value which the pointer points to. But i don't get the part where the string prints out ijool

Can someone help me out?

Synxis
  • 9,236
  • 2
  • 42
  • 64
Orthodex
  • 61
  • 11
  • 4
    I'm actually surprised this doesn't outright crash. You're modifying what should be read-only memory. Then again, its Turbo C++, so non-standard at this point its laughable. – WhozCraig Mar 14 '13 at 17:42
  • 11
    If possible, go and get another teacher. – stefan Mar 14 '13 at 17:43
  • 7
    It's undefined behavior, so it can print whatever it wants to. Or not print anything. Or set your house on fire. – Fred Larson Mar 14 '13 at 17:46
  • 3
    Please tell your teacher that he's an idiot. If he requests clarification, feel free to have him contact me. My contact information is public. – Nik Bougalis Mar 14 '13 at 17:46
  • 1
    @NikBougalis "idiot" might get OP into trouble. But pointing out the dodgyness of the code, yes. – Boann Mar 14 '13 at 17:49
  • 2
    I was being sarcastic... just barely. This code is a *disaster* and any "teacher" that hands this out to students ought to be called an idiot. – Nik Bougalis Mar 14 '13 at 17:49
  • Your teacher seriously gave you *this* code ? – Synxis Mar 14 '13 at 17:53
  • I hope your teacher gave your whole class the code and told everybody to execute it and report back the results. Hopefully there will be different results depending on the compilers and platforms. – Thomas Matthews Mar 14 '13 at 19:04
  • Ok guys i viewed all the answers and comments.Thing is' when I compile it in my (old) Turbo, it compiles everything nicely and prints the same output irrespective of the computer... – Orthodex Mar 20 '13 at 15:33

5 Answers5

5

The program you showed is non-standard and ill-formed (and should not compile).

"Small" problems:

  • The proper header for input/output streams in C++ is <iostream>, not <iostream.h>
  • main() returns an int, not a void.
  • cout and endl cannot be used without a using namespace std; at the beginning of the file, or better: use std::cout and std::endl.

"Core" problems:

  • char* p = "School"; is a pointer to string litteral. This conversion is valid in C++03 and deprecated in C++11. Aside from that, normally string litterals are read only, and attempts to modify them often result in segfaults (and modifying a string litteral is undefined behvior by the standard). So, you have undefined behavior everytime you use p, because you modify what it points to, which is the string litteral.
  • More subtle (and the practical explanation): you are modifying p several times in the line std::cout<<p<<","<<++(*(p--))<<","<<++(*(p++))<<std::endl;. It is undefined behavior. The order used for the operations on p is not defined, here it seems the compiler starts from the right. You can see sequence points, sequence before/after for a better explanation.

You might be interested with the live code here, which is more like what you seemed to expect from your program.

Community
  • 1
  • 1
Synxis
  • 9,236
  • 2
  • 42
  • 64
4

Let's assume you correct:

  1. the header to <iostream> - there is no iostream.h header
  2. your uses of cout and endl with std::cout and std::endl respectively
  3. the return type of main to int

Okay,

char *p = "School";

The string literal "School" is of type "array of 7 const char." The conversion to char* was deprecated in C++03. In C++11, this is invalid.

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

Here we hit undefined behaviour. As I said before, the chars in a string literal are const. You simply can't modify them. The prefix ++ here will attempt to modify the S character in the string literal.

So from this point onwards, there's no use making conjectures about what should happen. You have undefined behaviour. Anything can happen.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
3

Even if the preceding lines were legal, this line is also undefined behavior, which means that you cannot accurately predict what the output will be:

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

Notice how it modifies the value of p multiple times on that line (really between sequence points)? That's not allowed. At best you can say "on this compiler with this run-time library and this environment at this moment of execution I observed the following behavior", but because it is undefined behavior you can't count on it to do the same thing every time you run the program, or even if the same code is encountered multiple times within the same run of the program.

Bill
  • 14,257
  • 4
  • 43
  • 55
  • multiple modifications 'on the same line' are allowed, eg. `for ( int x = 0; x++ < 10; ++x ) ;` - if you don't express the restriction clearly, then someone may try and fix the code by adding new lines between the sub-expressions. – Pete Kirkham Mar 14 '13 at 18:22
  • True, I was trying to avoid having to delve into sequence points. – Bill Mar 14 '13 at 20:20
  • "on this compiler with this run-time library and this environment _at this time_ I observed the following behavior" Undefined behavior doesn't have to be and sometimes isn't consistent even within the same run of a program. (Though this particular situation ought to be consistent within a compiler version) – Mooing Duck Mar 14 '13 at 20:25
  • True, I was lazy given the trivial nature of this program. :) – Bill Mar 14 '13 at 20:28
1

There are at least three problems with this code (and maybe more; I'm not a C++ expert).

The first problem is that string constants like should not be modified as they can be placed in read-only parts of the program memory that the OS maps directly to the exe file on disk (the OS may share them between several running instances of that same program for example, or avoid those parts of memory needing to be written to the swap file when RAM is low, as it knows it can get the original from the exe). The example crashes on my compiler, for example. To modify the string you should allocate a modifiable duplicate of the string, such as with strdup.

The second problem is it's using cout and endl from the std namespace without declaring that. You should prefix their accesses with std:: or add a using namespace std; declaration.

The third problem is that the order in which the operations on the second cout line happen is undefined behavior, leading to the apparently mysterious change of the string between the time it was displayed at the end of the first cout line and the next line.

Since this code is not intended to do anything in particular, there are different, valid ways you could fix it. This will probably run:

#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);
}

(On my compiler this outputs: T,chool, diool,i,d.)

It still has undefined behavior though. To fix that, rework the second cout line as follows:

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

That should give T,chool, chool,d,U (assuming a character set that has A to Z in order).

Boann
  • 48,794
  • 16
  • 117
  • 146
  • `char b[] = "School"; char* p = b;` is easier and safer than `strdup`, since you have a memory leak. – Mooing Duck Mar 14 '13 at 20:27
  • 1
    After all this pointer arithmetic, it looks like `p` is not pointing at the same value that `strdup` returned, so `free` will not work correctly. – Bill Mar 14 '13 at 20:45
0
  1. p++ moves the position of p from "School" to "chool". Before that, since it is p++, not ++p, it increments the value of the char. Now c = "T" from "S"
  2. When you output p, you output the remainder of p, which we identified before as "chool".
  3. Since it is best to learn from trial and error, run this code with a debugger. That is a great tool which will follow you forever. That will help for the second set of cout statements. If you need help with gdb or VS debugger, we can walk through it.
msmith81886
  • 2,286
  • 2
  • 20
  • 27