Printing a char pointer ... what's going on?
I'm new to C and I have a question about char pointers and what it will print. take a look:
int main()
{
char *p1="ABCD";
p1="EFG";
printf ("%s",p1);
return 0;
}
it will print EFG
and now:
int main()
{
char *p1="ABCD";
//p1="EFG";
printf ("%s",p1);
return 0;
}
and he will give you ABCD
What I am not getting is what exactly *p1
? Is this the number of addresses containing the value char
? Is it char
?
what's in *p1
right now? Why is this const
?
source to share
From the C standard:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
EXAMPLE 8 The declaration
char s[] = "abc", t[3] = "abc";
defines โโplainโโ char array objects s and t whose elements are initialized with character string literals.
This declaration is identical to
char s[] = { 'a', 'b', 'c', '\0' },
t[] = { 'a', 'b', 'c' };
The contents of the arrays are modifiable. On the other hand, the declaration
char *p = "abc";
defines p with type โโpointer to charโโ and initializes it to point to an object
with type โโarray of charโโ with length 4 whose elements are initialized with a
character string literal. If an attempt is made to use p to modify the contents
of the array, the behavior is undefined.
In other words:
1) char *p1;
declares a variable (p1) which is a pointer. Pointer, p1 can be changed.
2) char *p1 = "ABCD";
declares p1 (same as "1") and also initializes the data it points to (initializes it only for a read-only character array 5 ABC \ 0).
Thus, you can change the address of "p1" (you can point it to "EFG", assign it to NULL, etc., etc.). But you CANNOT safely modify the data itself. You will probably get an "access violation" if you try to overwrite "ABCD". The exact behavior is "undefined" - something might happen.
3) char p2[] = "ABCD";
declares a variable (p2) which is an array. It allocates 5 characters and initializes the data "ABCD \ 0".
An array is read-write (you can change the data in the array), but the variable "p2" cannot be changed (you cannot change p2 to a different address - because it is not a pointer).
4) So what's the "difference" between a char * pointer and a char [] array? Here's a good discussion:
source to share
p1
is a pointer char
that contains the base address or the start address or the address of the first element of a string assigned to it by an operator =
.
In your first code, you assigned base address "ABCD" to it and then base address "EFG" [which overwrites the previous value] and finally prints it. Thus, the last value ["EFG"] is printed.
In the second case, you assign the base address "ABCD" and print it. So he prints ABCD
. It may be worth mentioning, the format specifier %s
in printf()
awaiting the start address of the string with zero termination, which is here indicated p1
.
As per the part, the const
value of the string pointed p1
to is constant in this case, since string literals are usually stored in read-only memory locations. Values โโthat change values โโare p[1] = 's'
not allowed. However, the pointer is p1
not const
, so it can be reassigned to a new value p1="EFG";
by right.
source to share
p1
is a char pointer that contains the address where the compiler puts "ABCD" into memory. The address has the first character in the array.
When you have char *p1 = "ABCD";
, you simply assign the value to the address contained in p1
. When you reassign p1 = "EFG";
, you reassign the pointer to store the new address (where "EFG" is located)
printf ("%s",p1);
prints the contents of memory at position p1
.
source to share
Initially, p1 is declared as a char pointer and points to "ABCD" (base address "ABCD").
Later the pointer points to "EFG" (contains the base address "EFG")
+----+ +---+
|ABCD| |EFG|
+----+ +---+
1000 2000
char *p1="ABCD";
+----+
before |1000|
+----+
p1
p1="EFG";
After +----+
|2000|
+----+
p1
source to share
int main()
{
char *p1="ABCD";
p1="EFG";
printf ("%s",p1);
return 0;
}
Required is missing #include <stdio.>
. Without it, your compiler might let you get away with the call printf
, but that doesn't guarantee it will work. And a minor point: there int main()
should be int main(void)
.
There is quite a lot going on in this program, and some of it is quite subtle.
char *p1 = "ABCD";
"ABCD"
- string literal. It defines an anonymous array object of type char[5]
(4 for the characters you specified plus 1 for the '\0'
null character , which marks the end of the string). This object has a static storage duration, which means that it exists throughout the entire execution of your program (as opposed to a local variable, for example, which ceases to exist when it goes out of scope (which is a slight simplification)).
In most contexts, an array expression is implicitly converted to a pointer to its first element. So, p1
initialized to point to a character 'A'
, the first character of this anonymous array object.
p1
should be defined as const char *p1 = ...
. This is not required, but it will help the compiler catch any attempt to modify the array object. (The object is not const
, but changing it has undefined behavior.)
p1 = "EFG";
Now the value stored in p1
is flushed and replaced with the new pointer value, this time pointing to a 'E'
string literal "EFG"
. (So โโthere was no point in initializing it, but that's okay.)
printf("%s", p1);
Here we are passing a value p1
(pointer value) to a function printf
.
At this point, the value *p1
is equal 'E'
and has a type char
. But it printf
can print the whole line "EFG"
. This is done using pointer arithmetic. Somewhere in the implementation printf
there is a loop that takes the pointer value that was passed in, looks for it to get the printable character value, and then increments the pointer to point to the next character in the string ( 'F'
). This loop continues until it reaches the '\0'
null character , which marks the end of the line; that the null character is not printed.
Since arrays are in some sense "second-class citizens" in C, most operations on array objects are done this way, using pointers to array elements to traverse the array. (You can also use indexing notation arr[i]
, which does much the same thing.) printf
Doesn't have direct access to the array object itself; it relies on a pointer (on its first element) to determine where the array is in memory and on a terminator '\0'
to determine where the string ends.
The second program is the same, except it is p1
not reassigned, so a line is printed "ABCD"
.
The relationship between arrays and pointers in C can be confusing. Section 6 of comp.lang.c often asks the question . It is very helpful to explain this.
source to share
I donโt understand what exactly
*p1
? Is this the number of addresses containing the char value? Is it char?
If you are talking about *p1
in an ad
char *p1 = "ABCD";
that *
indicates what p1
is a pointer to char
(actually const char
in this case). p1
simply points to the first character of a string literal ABCD
.
If you ask about *p1
how in
printf("%c", *p1);
then *
here is the indirection operator, and *p1
means the value of the symbol p1
that is A
. *p1
is equivalent p1[0]
.
Statement
p1 = "DEF";
let p1
points to the first character of a string literal DEF
.
Why is this
const
?
String literals are stored in a read-only section of memory.
char *p1 = "ABCD";
equivalent to
char const *p1 = "ABCD";
This means that you cannot change the string literal.
*p1 = 'a'; // WRONG. Invokes undefined behavior.
source to share
What I don't get is what exactly * p1 is! is it the address number that contains the char value? is it char? what is in * p1 right now?
Type *p1
- char
. Its meaning is symbol 'A'
.
why is he
const
?
String literals such as "ABCD"
are placed in permanent storage. Changing them with p
is the reason for undefined behavior. Therefore, *p1
read-only, i.e. A const
.
source to share
What I don't get is what exactly * p1 is! is it the address number that contains the char value? is it char? what is in * p1 right now?
The value *p1
is equal p1[0]
, that is, the char
values 'E'
in your first program and the values 'A'
in your second program.
why is it const?
It's not const
in C (it's in C ++), but string literals are listed as unmodifiable in C, which means trying to change *p1
causes undefined behavior.
source to share