Question

I'm working through K&R second edition, chapter 5.

On page 87, pointers to character arrays are introduced as:

char *pmessage;
pmessage = "Now is the time";

How does one know that pmessage is a pointer to a character array, and not a pointer to a single character?

To expand, on page 94, the following function is defined:

/* month_name: return the name of the n-th month */
char *month_name(int n)
{
    static char *name[] = {
        "Illegal month",
        "January", "February", "March",
        ...
    };

    return (n < 1 || n > 12) ? name[0] : name[n];
}

If one were simply provided with the function declaration for the above, how could one know whether a single character or a character array is returned?

If one were to assume the return from month_name() is a character array and iterate over it until a NULL is encountered, but the return was in fact a single character then is there not the potential for a segmentation fault?

Could somebody please demonstrate the declaration and assignment of a pointer to a single character vs a character array, their usage with functions and identification of which has been returned?

Was it helpful?

Solution 4

How does one know that pmessage is a pointer to a character array, and not a pointer to a single character?

You don't. At least, there's no way to tell from the pointer value itself whether it points to a single char or the first element of an array of char. It can be used either way.

You have to rely on context or specify explicitly how the pointer is to be used. For example, scanf uses different conversion specifiers in order to determine whether a pointer is pointing to a single char:

char single_char;
scanf( " %c", &single_char );

or an array of char:

char array_of_char[N];
scanf( "%s", &array_of_char[0] );

Remember that when it isn't the operand of the sizeof or unary & operators or a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of "pointer to T", and the value of the expression will be the address of the first element of the array, so that last line could also be written

scanf( "%s", array_of_char );

Because of that conversion rule, anytime you pass an array expression to a function, what the function actually receives is a pointer value. In fact, the function declarations

void foo( char str[N] );

and

void foo( char str[] );

are equivalent to

void foo( char *str );

All three treat str as a pointer to char.

OTHER TIPS

So what you have is a string literal which is an array of char with static storage duration:

"Now is the time"

in most contexts an array will decay into a pointer to the first element which is what happens here:

pmessage = "Now is the time";

You need to design and document your interface in such a way that you know what to expect for the input and output. There is no run-time information to tell the nature of what is being pointed to.

For example if we look at the man page of strtok it tells us:

Each call to strtok() returns a pointer to a null-terminated string containing the next token.

and so the programmer knows exactly what to expect and deals with the result accordingly.

In the case where you have a pointer to a single char and instead it like a C style string then you will have undefined behavior because you will be accessing memory out of bounds. A segmentation fault is one possibility but being undefined just means the result is unpredictable.

What does

char *pmessage;
pmessage = "Now is the time";  

mean?
char *pmessage; means that you declared pmessage as a pointer to char
pmessage = "Now is the time"; means that pmessage now points to the first character of the string literal Now is the time.

When you return pmessage from a function then a pointer to string literal is returned.
If you will print pmessage with %c specifier then it will print N and if you will print it with %s then it will print the entire string literal.

printf("%c\n", *N);     // 'N' will be printed
printf("%s\n", N);      //  "Now is the time" will be printed 

Strange as it seems, C trusts the intelligence of the programmer. If I see a function such as:

/* month_name: return the name of the n-th month */
char *month_name(int n)
{
    static char *name[] = {
        "Illegal month",
        "January", "February", "March",
        ...
    };

    return (n < 1 || n > 12) ? name[0] : name[n];
}

I look at the documentation and read that it returns a NUL-terminated string that is a pointer to statically allocated memory. That is enough for me to treat the return value as I should.

If the creator of the function changes the return value in a future release to a different kind of string, they better shout it out loud, change the function name, or make it very clear otherwise it's very bad behavior from their side.

If I on the other hand fail to treat the return value correctly even though it's documented properly, well I wouldn't be so intelligent then and perhaps cut out to be a Java developer.

Lastly, if the function is not documented, find its owner and burn his house.1

1 if it's in a library this is released! Don't burn people's house as soon as they start coding a library! ^_^

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top