Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Should I Define/Declare String Constants

Tags:

c

I've always used string constants in C as one of the following

char *filename = "foo.txt";
const char *s = "bar";    /* preferably this or the next one */
const char * const s3 = "baz":

But, after reading this, now I'm wondering, should I be declaring my string constants as

const char s4[] = "bux";

?

Please note that linked question suggested as a duplicate is different because this one is specifically asking about constant strings. I know how the types are different and how they are stored. The array version in that question is not const-qualified. This was a simple question as to whether I should use constant array for constant strings vs. the pointer version I had been using. The answers here have answered my question, when two days of searching on SO and Google did not yield an exact answer. Thanks to these answers, I've learned that the compiler can do special things when the array is marked const, and there are indeed (at least one) case where I will now be using the array version.

like image 502
RastaJedi Avatar asked Mar 04 '19 01:03

RastaJedi


People also ask

How do you declare a string constant?

C string constants can be declared using either pointer syntax or array syntax: // Option 1: using pointer syntax. const char *ptr = "Lorem ipsum"; // Option 2: using array syntax.

How do you define and declare constant?

You use the Const statement to declare a constant and set its value. By declaring a constant, you assign a meaningful name to a value. Once a constant is declared, it cannot be modified or assigned a new value. You declare a constant within a procedure or in the declarations section of a module, class, or structure.

How do you declare a constant string variable in C++?

To define a string constant in C++, you have to include the string header library, then create the string constant using this class and the const keyword.

How do you define a string in C using #define?

Strings are defined as an array of characters. The difference between a character array and a string is the string is terminated with a special character '\0'. Declaration of strings: Declaring a string is as simple as declaring a one-dimensional array.


2 Answers

Pointer and arrays are different. Defining string constants as pointers or arrays fits different purposes.

When you define a global string constant that is not subject to change, I would recommend you make it a const array:

const char product_name[] = "The program version 3";

Defining it as const char *product_name = "The program version 3"; actually defines 2 objects: the string constant itself, which will reside in a constant segment, and the pointer which can be changed to point to another string or set to NULL.

Conversely, defining a string constant as a local variable would be better done as a local pointer variable of type const char *, initialized with the address of a string constant:

int main() {
    const char *s1 = "world";
    printf("Hello %s\n", s1);
    return 0;
}

If you define this one as an array, depending on the compiler and usage inside the function, the code will make space for the array on the stack and initialize it by copying the string constant into it, a more costly operation for long strings.

Note also that const char const *s3 = "baz"; is a redundant form of const char *s3 = "baz";. It is different from const char * const s3 = "baz"; which defines a constant pointer to a constant array of characters.

Finally, string constants are immutable and as such should have type const char []. The C Standard purposely allows programmers to store their addresses into non const pointers as in char *s2 = "hello"; to avoid producing warnings for legacy code. In new code, it is highly advisable to always use const char * pointers to manipulate string constants. This may force you to declare function arguments as const char * when the function does not change the string contents. This process is known as constification and avoid subtile bugs.

Note that some functions violate this const propagation: strchr() does not modify the string received, declared as const char *, but returns a char *. It is therefore possible to store a pointer to a string constant into a plain char * pointer this way:

char *p = strchr("Hello World\n", 'H');

This problem is solved in C++ via overloading. C programmers must deal with this as a shortcoming. An even more annoying situation is that of strtol() where the address of a char * is passed and a cast is required to preserve proper constness.

like image 56
chqrlie Avatar answered Oct 08 '22 08:10

chqrlie


The linked article explores a small artificial situation, and the difference demonstrated vanishes if you insert const after * in const char *ptr = "Lorum ipsum"; (tested in Apple LLVM 10.0.0 with clang-1000.11.45.5).

The fact the compiler had to load ptr arose entirely from the fact it could be changed in some other module not visible to the compiler. Making the pointer const eliminates that, and the compiler can prepare the address of the string directly, without loading the pointer.

If you are going to declare a pointer to a string and never change the pointer, then declare it as static const char * const ptr = "string";, and the compiler can happily provide the address of the string whenever the value of ptr is used. It does not need to actually load the contents of ptr from memory, since it can never change and will be known to point to wherever the compiler chooses to store the string. This is then the same as static const char array[] = "string";—whenever the address of the array is needed, the compiler can provide it from its knowledge of where it chose to store the array.

Furthermore, with the static specifier, ptr cannot be known outside the translation unit (the file being compiled), so the compiler can remove it during optimization (as long as you have not taken its address, perhaps when passing it to another routine outside the translation unit). The result should be no differences between the pointer method and the array method.

Rule of thumb: Tell the compiler as much as you know about stuff: If it will never change, mark it const. If it is local to the current module, mark it static. The more information the compiler has, the more it can optimize.

like image 36
Eric Postpischil Avatar answered Oct 08 '22 08:10

Eric Postpischil