Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Char pointers and the printf function

Tags:

c

pointers

printf

I was trying to learn pointers and I wrote the following code to print the value of the pointer:

#include <stdio.h>

    int main(void) {
        char *p = "abc";
        printf("%c",*p);
        return 0;
    }

The output is:

a

however, if I change the above code to:

#include <stdio.h>

int main(void) {
    char *p = "abc";
    printf(p);
    return 0;
}

I get the output:

abc

I don't understand the following 2 things:

  1. why did printf not require a format specifier in the second case? Is printf(pointer_name) enough to print the value of the pointer?

  2. as per my understanding (which is very little), *p points to a contiguous block of memory that contains abc. I expected both outputs to be the same, i.e.

abc

are the different outputs because of the different ways of printing?

Edit 1

Additionally, the following code produces a runtime error. Why so?

 #include <stdio.h>

    int main(void) {
        char *p = "abc";
        printf(*p);
        return 0;
    }
like image 752
Fabulous Avatar asked Oct 12 '16 15:10

Fabulous


People also ask

What is a char pointer?

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.

What is a char * in C?

The abbreviation char is used as a reserved keyword in some programming languages, such as C, C++, C#, and Java. It is short for character, which is a data type that holds one character (letter, number, etc.) of data. For example, the value of a char variable could be any one-character value, such as 'A', '4', or '#'.

How do I assign a value to a char pointer?

char ptr* = "Hello World"; It allocates 12 consecutive bytes for string literal "Hello World" and 4 extra bytes for pointer variable ptr . And assigns the address of the string literal to ptr . So, in this case, a total of 16 bytes are allocated.


1 Answers

For your first question, the printf function (and family) takes a string as first argument (i.e. a const char *). That string could contain format codes that the printf function will replace with the corresponding argument. The rest of the text is printed as-is, verbatim. And that's what is happening when you pass p as the first argument.

Do note that using printf this way is highly unrecommended, especially if the string is contains input from a user. If the user adds formatting codes in the string, and you don't provide the correct arguments then you will have undefined behavior. It could even lead to security holes.

For your second question, the variable p points to some memory. The expression *p dereferences the pointer to give you a single character, namely the one that p is actually pointing to, which is p[0].

Think of p like this:

+---+      +-----+-----+-----+------+
| p | ---> | 'a' | 'b' | 'c' | '\0' |
+---+      +-----+-----+-----+------+

The variable p doesn't really point to a "string", it only points to some single location in memory, namely the first character in the string "abc". It's the functions using p that treat that memory as a sequence of characters.

Furthermore, constant string literals are actually stored as (read-only) arrays of the number of character in the string plus one for the string terminator.

Also, to help you understand why *p is the same as p[0] you need to know that for any pointer or array p and valid index i, the expressions p[i] is equal to *(p + i). To get the first character, you have index 0, which means you have p[0] which then should be equal to *(p + 0). Adding zero to anything is a no-op, so *(p + 0) is the same as *(p) which is the same as *p. Therefore p[0] is equal to *p.


Regarding your edit (where you do printf(*p)), since *p returns the value of the first "element" pointed to by p (i.e. p[0]) you are passing a single character as the pointer to the format string. This will lead the compiler to convert it to a pointer which is pointing to whatever address has the value of that single character (it doesn't convert the character to a pointer to the character). This address is not a very valid address (in the ASCII alphabet 'a' has the value 97 which is the address where the program will look for the string to print) and you will have undefined behavior.

like image 76
Some programmer dude Avatar answered Sep 17 '22 14:09

Some programmer dude