CaitlinG
CaitlinG

Reputation: 2015

Pointer to a string and the difference between assignment and dereferencing

In the following code:

#include <stdio.h>

int main(void) {
    char* message = "Hello C Programmer!";
    printf("%s", message);

    return 0;
}

I don't fully understand why it wasn't necessary to prepend an '*' to message in the printf call. I was under the assumption that message, since it is a pointer to a char, the first letter in the double quoted string, would display the address of the 'H'.

Upvotes: 0

Views: 105

Answers (4)

Carcigenicate
Carcigenicate

Reputation: 45743

In addition, a pointer must be used here.

If you passed a character, it would be passed by value, and printf would lose the original address of the character. That means it would no longer be possible to access the characters that come after the first.

You need to pass a pointer by value to ensure you're retaining the original address of the head of the string.

Upvotes: 1

Vlad from Moscow
Vlad from Moscow

Reputation: 310950

The conversion specifier %s is used to output strings (a sequence of characters terminated with the zero character '\0') pointers to first characters of which are passed to the function printf as an argument.

You can imagine that the function internally executes the following loop

for ( ; *message != '\0'; ++message )
{
    printf( "%c", *message );
} 

If you will supply the expression *message then it has type char and the function printf will try to interpret its value that is character 'H' as a value of a pointer. As result the function call will have undefined behavior.

To output the value of the pointer message you should use the conversion specifier %p like

printf( "%p", message );

Or as an integer value as for example

#include <stdio.h>
#include <inttypes.h>

int main(void) 
{
    char *message = "Hello C Programmer!";

    printf( "The value of the pointer message is %" PRIiPTR "\n", ( intptr_t )message );

    return 0;
}

Upvotes: 2

Steve Summit
Steve Summit

Reputation: 47933

You're right that message is a pointer, of type "pointer to char", or char *. So if you were trying to print a character (an individual character), you would certainly have needed a *:

printf("first character: %c\n", *message);

In a printf format specifier, %c expects a character, which is what *message gives you.

But you weren't trying to print a single character, you were trying to print the whole string. And in a printf format specifier, %s expects a pointer to a character, the first of usually several characters to print. So

printf("entire string: %s\n", message);

is correct.

Upvotes: 3

Barmar
Barmar

Reputation: 780879

The %s format operator requires its corresponding argument to be a char * pointer. It prints the entire string that begins at that address. A string is a sequence of characters ending with a null byte. That's why this prints the entire message.

If you supply an array as the corresponding argument, it's automatically converted to a pointer to the first character of the array. In general, whenever an array is used as an r-value, it undergoes this conversion.

You don't need to use the * operator because the argument is supposed to be a pointer. If you used *message you would only pass the 'H' character to printf(). You would do this if you were using the %c format instead of %s -- its corresponding argument should be a char.

Upvotes: 5

Related Questions