问题
i'm new to C and i've got 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 it will give you ABCD
The point that I don't get is what exactly *p1
is ?
Is it a number of an address that contains a char
value ?
Is it a char
?
what is in *p1
right now ? Why is it const
?
回答1:
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) that is a pointer. The pointer, p1 can be changed.
2) char *p1 = "ABCD";
declares p1 (same as "1") and also initializes the data it points to (initializes it to the read-only, 5-lelement character array "ABCD\0").
So you can change the address "p1" points to (you can make it point to "EFG", assign it to NULL, etc. etc). But you CANNOT safely change the data itself. You'll probably get an "access violation" if you try to overwrite "ABCD". The exact behavior is "undefined" - ANYTHING can happen.
3) char p2[] = "ABCD";
declares a variable (p2) that is an array. It allocates 5 characters, and initializes the data to "ABCD\0".
The array is read-write (you can change the data in the array), but the variable "p2" cannot be changed (you cannot change p2 to point to a different address - because it's not a pointer).
4) So what's the "difference" between a char *pointer and a char array[]? Here is a good discussion:
http://c-faq.com/aryptr/aryptrequiv.html
回答2:
int main()
{
char *p1="ABCD";
p1="EFG";
printf ("%s",p1);
return 0;
}
This is missing the required #include <stdio.>
. Without it, your compiler might let you get away with calling printf
, but it's not guaranteed to work. And a minor point: int main()
should be int main(void)
.
There's actually quite a lot going on in this program, and some of it is rather subtle.
char *p1 = "ABCD";
"ABCD"
is a string literal. It specifies an anonymous array object of type char[5]
(4 for the characters you specified plus 1 for the '\0'
null character that marks the end of the string). That object has static storage duration, which means that it exists during the entire execution of your program (unlike a local variable, for example, which ceases to exist when it goes out of scope (that's a slight oversimplification)).
An array expression is, in most contexts, implicitly converted to a pointer to its first element. So p1
is initialized to point to the character 'A'
, the first character of that anonymous array object.
p1
should be defined as const char *p1 = ...
. It's not actually required, but it will help the compiler catch any attempt to modify the array object. (The object is not const
, but modifying it has undefined behavior.)
p1 = "EFG";
Now the value stored in p1
is clobbered and replaced by a new pointer value, this time pointing to the 'E'
of the string literal "EFG"
. (So there was no point in initializing it, but that's ok.)
printf("%s", p1);
Here we pass the value of p1
(a pointer value) to the printf
function.
At this point, the value of *p1
is 'E'
, and is of type char
. But printf
is able to print the entire string "EFG"
. It uses pointer arithmetic to do so. Somewhere in the implementation of printf
, there's a loop that takes the pointer value that was passed in, dereferences it to obtain the character value to be printed, and then increments the pointer so it points to the next character of the string ('F'
). This loop continues until it reaches the '\0'
null character that marks the end of the string; that null character is not printed.
Since arrays are in a sense "second-class citizens" in C, most operations on array objects are done this way, using pointers to the array elements to traverse the array. (You can also use indexing notation arr[i]
, which does essentially the same thing.) printf
doesn't have direct access to the array object itself; it relies on the pointer (to its first element) to determine where the array is in memory, and on the '\0'
terminator to determine where the string ends.
The second program is the same, except that p1
is not reassigned, so the string "ABCD"
is printed.
The relationship between arrays and pointers in C can be confusing. Section 6 of the comp.lang.c FAQ does a very good job of explaining it.
回答3:
p1
is a char pointer that holds the address of where the compiler put "ABCD" in memory. The address is of the first character in the array.
When you have char *p1 = "ABCD";
you are just assigning the value of the address held in p1
.
When you reassign p1 = "EFG";
you are reassigning the pointer to hold a new address (where "EFG" is)
printf ("%s",p1);
prints the contents of memory in the location p1
points to.
回答4:
Initially p1 is declared as a char pointer and points to "ABCD" (base address of "ABCD").
Later the pointer points to "EFG" (contains the base address of "EFG")
+----+ +---+
|ABCD| |EFG|
+----+ +---+
1000 2000
char *p1="ABCD";
+----+
before |1000|
+----+
p1
p1="EFG";
After +----+
|2000|
+----+
p1
回答5:
p1
is a char
pointer which holds the base address or starting address or the address of the first element of the string assigned to it using =
operator.
In your first code, you've assigned the base address of "ABCD" to it, later the base address of "EFG" [which overwrites the previous value] and finally printing it. So, the latest value ["EFG"] is printed.
In second case, you're assigning the base address of "ABCD" and printing it. So it prints ABCD
.
Maybe worthy to mention, the %s
format specifier in printf()
expects the starting address of a null-terminated string, which is here, pointed by p1
.
As per the const
part, the value of the string pointed by p1
is constant in this case, as string literals are usually stored in read-only memory locations. Means, altering the values, p[1] = 's'
is not allowed. However, the pointer p1
is not const
, so it can be re-assigned to a new value p1="EFG";
rightly.
回答6:
I don't get is what exactly
*p1
is ?
Is it a number of an address that contains a char value ? Is it a char ?
If you are talking about *p1
in the declaration
char *p1 = "ABCD";
then *
indicates that p1
is a pointer to char
(in fact const char
in this case). p1
just points to the first character of the string literal ABCD
.
If you are asking about *p1
as in
printf("%c", *p1);
then *
here is an indirection operator and *p1
means the value of the character p1
points to which is A
. *p1
is equivalent to p1[0]
.
The statement
p1 = "DEF";
let p1
point to first character of the string literal DEF
.
Why is it
const
?
String literals are stored in read-only section of memory.
char *p1 = "ABCD";
is equivalent to
char const *p1 = "ABCD";
This means that you can't modify a string literal.
*p1 = 'a'; // WRONG. Invokes undefined behavior.
回答7:
The point that i don't get is what exactly *p1 is ! is it a number of an address that contains a char value ? is it a char ? what is in *p1 right now ?
The type of *p1
is char
. Its value is the character 'A'
.
why is it
const
?
String literals, like "ABCD"
, are placed in read only memory. Modifying them through p
is cause for undefined behavior. That's why *p1
is read only, i.e. it's a const
.
回答8:
The point that i don't get is what exactly *p1 is ! is it a number of an address that contains a char value ? is it a char ? what is in *p1 right now ?
The value of *p1
is p1[0]
, that is a char
of value 'E'
in your first program and of value 'A'
in your second program.
why is it const ?
It is not const
in C (it is in in C++), but string literals are specified to be non-modifiable in C which means an attempt to modify *p1
invokes undefined behavior.
来源:https://stackoverflow.com/questions/27626795/printing-a-char-pointer-what-happens