Pointer Declaration

I just started learning c a couple days ago so I'm sure this is a dumb question.
If I change the declaration in the code below to:

char message[] = "Hello";

It works fine... displays "Helxo" as expected.

I was just curious why the following code doesn't work, it prints "Hello" instead of "Helxo"?

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

int main ()
{
    char* message = "Hello";

    *(message+3) = 'x';
    printf("%s", message);
	
    return 0;
}

When you initialize your pointer, you point it to the location returned by "Hello" which is not a valid pionter.
Try this:
1
2
3
4
5
6
7
8
9
10
11
int main ()
{
    char *message=new char[6];

    sprintf(message, "Hello");//set message to "Hello"

    message[3] = 'x';
    printf("%s", message);

    return 0;
}
Although Bazzy's solution does fix the problem, the explanation of why the original code didn't work is wrong.

The reason is because string literal "Hello" is being compiled into the code segment (ie, a non-writable memory page). On most OSes this code should bomb out (indeed on my linux box it does).



Thanks for your replies. Not being too bright, I'm still a little confused.

I don't understand why I can use
*(message+3) = 'x'
When message is defined as
char message[] = "Hello"

But not when it's defined as:
char *message = "Hello"
Especially since I can say:
message = "Goodbye"

To me both ways define a pointer to some text.
The book I'm reading actually says that defining message as an array creates a pointer constant (fixed length). Defining message as a pointer (*message) creates a pointer to a variable.

This may be just one of those things that I have to accept as "That's just the way it is".

Thanks again for your patience and help.
Here's the key: in assignments, *pointer = value means literally "assign the value to the address pointed to by the pointer", but in initializations, *pointer = address means "create a pointer and assign the address to it". In assignments, you assign to *pointer, but in initializations, even though you write *pointer, you're assigning to pointer. This isn't how I'd write the C++ standard, but that's how they decided to make it, so you kind of have to deal with it.

In case you're confused about why I keep talking about *pointer as opposed to pointer, here's a brief lesson on pointers:
A pointer is a variable that stores a memory "address", or the number of a byte in the RAM. Obviously, the address isn't very interesting to most people, but what is interesting is the value at that byte. For this we have the dereferencing operator, "*". * means "the value at the address" in English. *message is "the value at the address message".

Pointers were probably my favorite thing to learn as a self-taught programmer, because I always seemed to find that other programmers, in schools, weren't taught the inside works of pointers. Here's a interesting bit of code, see if you can predict its output :) If you don't get it, don't worry about it, it's not really important to what you're doing, but if you do get it, you'll hopefully never have another pointer question again...
1
2
3
4
5
6
7
8
9
10
#include <iostream>

int main()
{
	std::cout << sizeof(short) << ' ' << sizeof(char) << '\n';	 	// the sizes of short and char, in BYTES
	unsigned short *integer = new unsigned short; 				//letting the OS assign an address to a pointer variable
	*integer = 65535; 							//assigning a number to sizeof(short) consecutive bytes (should be 2 consecutive bytes)
	std::cout << (unsigned short)(*((unsigned char*)integer)); 		//outputting 1 byte of the 2 bytes in *integer as an integer
	for (;;);
}

Hint: 65535 is 11111111 11111111 in binary (2 bytes full of 1s).
Last edited on
Still confused. I'm not sure where "*pointer = address" is coming into the picture.
I'm very clear on what a pointer is.
My first example defines a pointer to a char array and the second defines a pointer to a char variable.
I understand there are other ways to accomplish this, I'm just trying to understand the reason why the line...

*(message+3) ='x';

Works for...

char message[] = "Hello";

But does not work for...

char *message = "Hello";

When both are pointers to 6 bytes of memory. Why can I change the first 6 bytes but not the second?


Because it the first one you are saying "make a char pointer to some memory, and make the data equal to "Hello"". Whereas in the second one, you are saying "make a char pointer to a constant char array "Hello""
That's my point, I can modify the constant array using *(message+3), but not the other, that's what I don't understand.
*pointer = address comes into the picture in initializations, for instance "char *pointer = address". Sorry, I think I mean to write type *pointer = address; and *pointer = value;.

And yes, the problem is that the initializations are different.
char message[] = "Hello"; means "set the value of the array at address 'message' to 'Hello'".
char *message = "Hello"; means "set the address of the value of '*message' to 'Hello'".
The initializations mean different things, for no good reason (well, there are practical reasons, but it's not very logical).
Last edited on
Again, thanks for your patience. Unfortunately I'm just not getting it.

Isn't message, in both cases, a pointer? In both cases doesn't *message point to a character 'H' ?
when you declare a pointer like this: type* pointer=addres, the * only means that it is a pointer. The addres is the addres in memory it is pointing to. If you want to chance the value where the pointer is pointing to, you can use this (after you have declared the pointer):*pointer=value where the * means "value where pointer is pointing to".
If you still dont get it, read this: http://www.cplusplus.com/doc/tutorial/pointers.html
Last edited on
Again, I understand pointers, this is NOT my question. I started programming over 20 years ago using Assembly language, I programed in Assembly for several years before moving on to high level languages. So I understand pointers, addresses and the manipulation of computer memory.

My initial post in this topic explains my question.
Maybe this will be clearer...

This code works fine (displays an x)...

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main ()
{
	char message[] = "Hello";
	
	*(message+3) = 'x';
	
	printf("%c", *(message+3));

    return 0;
}



And this code works fine (displays an x)...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>

int main ()
{
	char txt[] = "Hello";
	char* message;
		
	message = txt;
	
	*(message+3) = 'x';
	printf("%c", *(message+3));

    return 0;
}


But this code doesn't...

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

int main ()
{
	char* message = "Hello";

	*(message+3) = 'x';
	printf("%c", *(message+3));

    return 0;
}


I'm just want to know why.
Do you get an error message when executing the last code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 #include <stdio.h>

 int main ()
{
	//Compiler places string literal "Hello" in READONLY memory.
    //compiler creates local variable message[] in READ/WRITE memory
    //and intitiales the the array by COPYING the string data from READONLY memory
    char message[] = "Hello";
	
	*(message+3) = 'x'; //changing READ/WRITE memory - OK
	
	printf("%c", *(message+3));

    return 0;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>

int main ()
{
	//Compiler places string literal "Hello" in READONLY memory.
    //compiler creates local variable txt[] in READ/WRITE memory
    //and intitiales the array by COPYING the string data from READONLY memory
    char txt[] = "Hello";
	char* message; 
		
	message = txt; //pointer points to txt[] which is in READ/WRITE memory
	
	*(message+3) = 'x';//changing READ/WRITE memory - OK
	printf("%c", *(message+3));

    return 0;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>

int main ()
{
	//Compiler places string literal "Hello" in READONLY memory.
    //and initialises pointer  to the address
    //of the string literal (which is in READONLY memory);	
    char* message = "Hello";

	*(message+3) = 'x'; //ERROR - attempting to change a location in READONLY memory
	printf("%c", *(message+3));

    return 0;
}
No errors when running the last code
Thanks Guestgulkan, that makes perfect sense.

Thanks to everyone for their input.
The reason is exactly as I stated above.

Given the following declaration:
 
const int x = 5;


you cannot modify the contents of x because it is const.

You can think of
 
char* message = "Hello";

like this, because this is essentially how the compiler treats it:

1
2
const char* __message = "Hello";
char* message = __message;


You cannot modify __message's contents because it is const, just like x was const in my previous example.

The result is that the compiler compiles the "Hello" constant into the code segment, not the data segment. The compiler puts the pointer--message-- into the data segment because the pointer is non-const.
Thanks JSmith, that's really makes sense, that's what I needed to know. So when I have code like this...

char* message = "This";

And later in code when I say...

*message = "That";

... the original constant ("This") in the code segment is unchanged but the variable (addressed by *message) in the Data segment is changed from "This" to That".

Correct, except the line of code should read

message = "That";

(no dereference).

With that fix, your example code is semantically equivalent to:

1
2
3
4
5
const char* __message1 = "This";
char* message = __message1;

const char* __message2 = "That";
message = __message2;


Topic archived. No new replies allowed.