Ryan Maguire
Ryan Maguire

Reputation: 107

Char Arrays as Compile-Time Constants

If we have a const char pointer initialized by a string literal, such as const char *str = "Hi!", then we cannot use str as a compile-time constant. This makes sense, str is a variable after all. But addresses are compile time constants, so we could use &str just fine.

The following workaround compiles with GCC and clang, with -Wall, -Wextra, -Wpedantic, -Weverything (clang only), and -std=c89).

#include <stdio.h>

/* Bad:
 *    static const char *str = "Hi!";
 */
static const char str[4] = {'H', 'i', '!', '\0'};
static struct {
    double x;
    const char *string;
} my_struct = {1.0, str};

int main(void)
{
    puts(my_struct.string);
    return 0;
}

After some searching, I was unable to find something in the C standard that would verify that this is legal and portable. My guess is that static const char str[4] is an array, so using str in the structs initialization is the same thing as using an address, which is a compile time constant, whereas using static const char *str is a pointer to an array, so using it amounts to using a variable, which is not a compile time constant.

Any references to the relevant sections in the standard are greatly appreciated.

Upvotes: 2

Views: 76

Answers (1)

Eric Postpischil
Eric Postpischil

Reputation: 223795

You seem to be asking whether str, having been defined as a static const char str[4], can be used to initialize a member of a static structure.

C 2024 6.6 specifies constant expressions and includes:

More latitude is permitted for constant expressions in initializers. Such a constant expression shall be, or evaluate to, one of the following:

— an address constant, or…

and:

An address constant is a null pointer, a pointer to an lvalue designating an object of static storage duration,…

str is an array, not a pointer. However, in this use, it is automatically converted to a pointer to its first element. That first element is an object of static storage duration, and hence str evaluates to a pointer to an object of static storage duration, so it may be used as an initializer.

Upvotes: 4

Related Questions