2

So this article is discussing the use of declaring a string literal like const char* foo = "foo" it ends with the claim:

const char *foo = "foo";
is almost never what you want. Instead, you want to use one of the following forms:

  • For a string meant to be exported:
    const char foo[] = "foo";
  • For a string meant to be used in the same source file:
    static const char foo[] = "foo";
  • For a string meant to be used across several source files for the same library:
    __attribute__((visibility("hidden"))) const char foo[] = "foo";

My understanding here is that const char* const foo = "foo" is equivalent to const char foo[] = "foo" simply because we're talking about a C-string pointer that can never be changed to point at anything else, whereas const char* foo = "foo" could be used to point at any other C-String.

Is this an accurate synopsis? Always use either const char* const or const char[]?

Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • 3
    An array is an array, and a pointer is a pointer. They are not the same thing, though an array can decay to a pointer. – JGroven May 25 '18 at 20:52
  • 2
    `const char foo[] = "foo"` is not a pointer. It is an independent array. So, formally there's no equivalence with `const char* const foo = "foo"`. The latter is indeed a pointer. – AnT stands with Russia May 25 '18 at 20:53
  • Found something here: https://stackoverflow.com/questions/18625674/c-difference-between-const-char-and-const-char – JeJo May 25 '18 at 20:53
  • A tiny nitpicking: Literals are *unnamed* constants, so `const char* foo` is not a literal, only `"foo"` is. – HolyBlackCat May 25 '18 at 20:54
  • 1
    `const char* const` will stop you from being able to call a lot of c-string functions – NathanOliver May 25 '18 at 20:56
  • @JGroven So you'd agree with the article that we should always use `const char foo[]`? – Jonathan Mee May 25 '18 at 21:06
  • @AnT So you'd agree with the article that we should always use `const char foo[]`? – Jonathan Mee May 25 '18 at 21:07
  • @JonathanMee I said no such thing. It's situational. – JGroven May 25 '18 at 21:08
  • @JGroven So it sounds like we both understand that a pointer and an array are different. Could you give me an example of a situation in which we'd prefer `const char* foo` to `const char foo[]` for referring to a string literal? – Jonathan Mee May 25 '18 at 21:12
  • @JonathanMee When you have a single character and you need a pointer for it, why would you bother with an array? – JGroven May 25 '18 at 21:18
  • @JGroven That does seem a bit silly, what about the case where you're working with a string literal? For example `"foo"`? – Jonathan Mee May 25 '18 at 21:20

3 Answers3

3

Let's get pedantic here.

char const * const p_foo = "foo";

The above defines a {constant} pointer to the {constant} character literal "foo". The pointer is to the single first character of the character literal.

const char bar[] = "bar";
  • The above defines a character array.
  • The character array is *read-only".
  • The character array is the length of the text literal "bar" plus a nul terminator (4 characters).
  • The contents of the text literal are copied into the array. (The compiler may optimize this step away).

Fundamentally, you have the difference between a pointer to the first character of a literal and an array.

The pointer is pointing to a single character. Incrementing the pointer may not point to a valid entity (since it is not an array, but a pointer to a single datum). There is an underlying assumption that the pointer can be incremented to the next character.

With an array you know that there are more than one character sequentially in memory (provided the array is of length 2 or more). You don't know if there is a terminating nul in the sequence (collection). You can assume that, but an array of characters does not guarantee that.

Usages
With the array declaration, the length of the text is known at compile time.

With the pointer declaration, you would need to use strlen to determine the length of the text at run-time. The run-time code doesn't know the length of the target data string; only a length of 1 can be guaranteed.

Sometimes, using static and const can help the compiler optimize.
For example:

static const char moo[] = "moo";

allows the compiler to access the text directly without creating an array variable and copying the text into the variable.

In a function that receives a pointer to a character, you can't guarantee that the pointer points to a valid location (the content of the pointer can be invalid).

Each declaration has its benefits and side-effects.
The choice is yours.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
2

As Thomas Matthews' answer states both a const char* and a const char* const are pointers, and a const char[] is an array.

But as justified here there are 3 problems with using pointers:

  1. Memory for the pointer's storage is required
  2. The indirection incurred by the pointer is required
  3. A pointer requires separate storage of an end pointer for the array or an array size

Ultimately as justified in the link:

The simple answer is that when declaring a variable you should prefer a const char[].

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
0

I do agree that an array decays into a pointer when being evaluated but there are a few functionalities that come only with an array. For example when you declare an array you have additional information as to what the size of the array is.

Also, for the fixed array case, memory is allocated specifically for foo. So you are allowed to change the contents of the array like you usually can and the array is destroyed, deallocating memory when it runs out of scope (typical local variable).

When you define it as a pointer, the compiler places foo into read-only memory, and then points to it (usually). Note that this is why most cases constant strings are defined as char* and even the compiler would warn you when you set it as a non constant pointer.

#include <iostream>
int main()
{
    char* a = "foo";
    return 0;
} 

This code would throw you a warning like:

ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings] char* a = "foo";

and any change you try to make to the string would typically lead to a segmentation fault.