Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

printing a char pointer ... what happens?

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 ?

like image 700
Behrus58 Avatar asked Dec 23 '14 19:12

Behrus58


People also ask

What does a char pointer do?

A pointer may be a special memory location that's capable of holding the address of another memory cell. So a personality pointer may be a pointer that will point to any location holding character only. Character array is employed to store characters in Contiguous Memory Location.

What happens when you cast a char pointer to an int pointer?

When casting character pointer to integer pointer, integer pointer holds some weird value, no where reasonably related to char or char ascii code. But while printing casted variable with '%c', it prints correct char value. Printing with '%d' gives some unknown numbers.

What is a char * in C?

char* is how you declare a pointer to a char variable. It's useful when you want a string with unknown length.


3 Answers

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

like image 146
paulsm4 Avatar answered Sep 29 '22 07:09

paulsm4


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.

like image 43
Keith Thompson Avatar answered Sep 29 '22 08:09

Keith Thompson


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.  
like image 45
haccks Avatar answered Sep 29 '22 09:09

haccks