-2

code1:



char *pc = "abc";     
cout&lt&lt*pc&lt&ltendl;

code2:



int *pi = 10 ;
cout&lt&lt*pi&lt&ltendl;

Why code1 prompt message of warn as "warning: deprecated conversion from string constant to 'char*'"; but code2 prompt message of error as " error: invalid conversion from 'int' to 'int*'".

【Q1】 As I see it, they are both mismatch, but why one getting warn and another getting error?

When I try to fix this like:

code3:



int *pi = (int*)10 ;  //compile correctly without error
cout&lt&lt*pi&lt&ltendl;      //get "segmentation fault"

code4:



char *pc = (char*)"abc";  //compile without warning    
cout&lt&lt*pc&lt&ltendl;         // output 'a'

【Q2】 Why cout<<*pi<< endl; in code3 get segmentation fault and cout<<*pc<< endl in code4 run correctly?

It seems to be a popular question, but little explanations have been made for the differences. Could someone help me out?

Thanks in advance.

Community
  • 1
  • 1
heming621
  • 3
  • 4

3 Answers3

2
  1. Try:

    const char *pc = "abc";     
    cout << pc << endl;
    
  2. Try:

    int pi = 10;
    cout << pi << endl;
    

In case 1 above, string literals are of type const char *

In case 2, you were declaring not an integer, but an integer pointer and assigning the ADDRESS 10 to the pointer, then trying to dereference it (effectively you were trying to access the data at memory address 10, which you probably don't have access to, which is why you get a crash)

kcraigie
  • 1,192
  • 5
  • 12
  • String literals are of type `const char[N]`. – chris Nov 01 '15 at 12:10
  • I've also thought about that. So theoretically, when I try to assign *pi a value that happen to be an address I have access to, like int *pi = (int*)Ox400898, then "cout< – heming621 Nov 01 '15 at 12:33
  • @heming621 yes that is technically correct but how could you possibly know that an integer resides at that location in memory and that you have access to it? Generally you allow the system to allocate your memory and give you an address. One small tweak to your example, the syntax would be `int *pi = (int*)0x400898` – kcraigie Nov 01 '15 at 15:09
0

While dangerous syntax perhaps, here foo does point to a valid spot in memory -- it is a character pointer to the beginning of "abc" (also known as 'a'):

char *foo = "abc";

But here:

int *pi = (int*)10 ;  //compile correctly without error
cout<<*pi<<endl;

pi is pointing to memory address 10, which is fine up until you try to deference that -- which is a big no-no since your program does not have access to that memory.

Jameson
  • 5,452
  • 5
  • 26
  • 44
  • thanks you for your answer. Can you give more detail of " here foo does point to a valid spot in memory". Do you mean that the foo in _char *foo = "abc";_ point to a valid spot in memory, while the foo in _int *foo = 10;_ does not point to a valid spot in memory ? If it is, why? – heming621 Nov 02 '15 at 02:46
  • Yes, that is what I mean. Because memory address wasn't allocated to the process, but "abc" was created within the process's memory space. Pick yourself up a copy of Andrew Tanenbaum's Modern Operating Systems text and read about memory management and processes. http://www.amazon.com/Modern-Operating-Systems-3rd-Edition/dp/0136006639 – Jameson Nov 02 '15 at 02:53
0
char *pc = "abc";

"abc" is what is called a string literal. It may not be stored in memory as you know it and probably cannot be changed. Trying to, for example

pc[1] = 'k';

will have unpredictable results, most likely crashing the program because that location cannot be written.

The compiler warning is telling you that you are assigning a pointer to a value you cannot or should not change to a pointer that will allow you to change the value. The quick fix here is to inform the compiler that you will not try to change "abc" and accept a slap-down by the compiler if you try.

const char *pc = "abc";

Writing to the memory referenced by pc will now generate a compiler warning, but better that than the program writing into invalid memory and doing something weird.

This is a warning rather than an error because there are huge volumes of ancient code that does exactly this sort of risky constant->non constant assignment but never try to write to the non-writable location and would stop compiling if this was an error. For now compilers simply flag the problem and suggest you fix it.

This code:

char *pc = (char*)"abc";  
cout<<*pc<<endl;         

does not crash, or otherwise exhibit bad behaviour, because the location holding "abc" is readable.

char *pc = (char*)"abc";  
cin >>*pc;         

would be very bad if not immediately fatal.

On the other hand,

int *pi = 10 ;

is a bit different. It makes a pointer to an integer that is at memory location 10, and that is almost certainly wrong. While char *pc = "abc"; carries risk, attempting to use memory locations that have not been assigned to the program is bad and probably fatal. You hope it is fatal, because the alternative is a not-so fun game of "Dude, where's my data?" Pointers are not integers, regardless of what you may have been told, and this generating an error forces a programmer to at least think before doing something stupid.

There are exceptions in driver and embedded programming where direct hardware access is common, but these are specified with casts and other tricks to ensure the compiler that you know what you are doing and something accessible really does exist at the specified address. Precisely what you do here:

int *pi = (int*)10 ;

But the program crashes when you try to print it because there is nothing allocated and accessible for your program to read at address 10. As you can see this is considered an error for good reason. You can neither read nor write, so it does not get the conditional pass the compiler offers for the readable but not writable "abc".

user4581301
  • 29,019
  • 5
  • 26
  • 45
  • But why the location holding "abc" is readable in code _char *pc = (char*)"abc"_ in your explanation ? And I try _char *pc = (char*)'A'; cout< – heming621 Nov 02 '15 at 03:32
  • @heming621 `'A'` is a character. It is a value, not a pointer to a value. Just like the integer, `'A'` does not convert to a pointer without brute force cast. `char *pc = (char*)'A';` assigns the value of `'A'`, 65, to pc. `cout < – user4581301 Nov 02 '15 at 18:46
  • Yes, _cout < – heming621 Nov 03 '15 at 10:17
  • What is the difference between _char *pc = (char*)'A'_ and _int *pi = (int*)65_? It seems only _pi_ get the value of address 0x41. – heming621 Nov 03 '15 at 10:22
  • @heming621 Because one of the most common things you do in C++ is print out text (and almost never print the address of the string) strings << has special handing for `char*` and prints out the pointed-to string rather than printing the address. There is no memory at address 65, so boom. – user4581301 Nov 03 '15 at 16:48