initializing char arrays in a way similar to initializing string literals

49,182

Solution 1

I might have found a way to do what i want though it isn't directly what I wanted, but it likely has the same effect.
First consider two following classes:

template <size_t size>
class Cont{
 public:
  char charArray[size];
};
template <size_t size>
class ArrayToUse{
 public:
  Cont<size> container;
  inline ArrayToUse(const Cont<size+1> & input):container(reinterpret_cast<const Cont<size> &>(input)){}
};

Before proceeding, you might want to go here and take a look at constant expression constructors and initialization types.
Now look at following code:

const Cont<12> container={"hello world"};
ArrayToUse<11> temp(container);
char (&charArray)[11]=temp.container.charArray;

Finally initializer text is written between two double quotations.

Solution 2

It's allowed in C to declare the array as follows, which will initialize it without copying the terminating '\0'

char c[3] = "foo";

But it's illegal in C++. I'm not aware of a trick that would allow it for C++. The C++ Standard further says

Rationale: When these non-terminated arrays are manipulated by standard string routines, there is potential for major catastrophe.
Effect on original feature: Deletion of semantically well-defined feature.
Difficulty of converting: Semantic transformation. The arrays must be declared one element bigger to contain the string terminating ’\0’.
How widely used: Seldom. This style of array initialization is seen as poor coding style.

Solution 3

There is no way of doing what you want. The first way of initializing the array specifies separate initializers for each character, which allows to explicitly leave off the '\0'. The second is initializing a character array from a character string, which in C/C++ is always terminated by a null character.

EDIT: corrected: 'character pointer' --> 'character array'

Solution 4

litb has the technically correct answer.

As for an opinion - I say just live with the 'waste' of the extra '\0'. So many bugs are the result of code expecting a terminating null where one isn't (this advice may seem to go directly against some other advice I gave just a day or two ago about not bothering to zero an entire buffer. I claim there's no contradiction - I still advocated null terminating the string in the buffer).

If you really can't live with the '\0' terminator because of some semantics in the data structure you're dealing with, such as it might be part of some larger packed structure, you can always init the array yourself (which I think should be no less efficient than what the compiler might have done for you):

#define MY_STRING_LITERAL "hello world"

char stringLiteral[sizeof(MY_STRING_LITERAL) - 1];

memcpy( stringLiteral, MY_STRING_LITERAL, sizeof(stringLiteral));
Share:
49,182
Pooria
Author by

Pooria

Updated on March 29, 2020

Comments

  • Pooria
    Pooria about 4 years

    Suppose I've following initialization of a char array:

    char charArray[]={'h','e','l','l','o',' ','w','o','r','l','d'};
    

    and I also have following initialization of a string literal:

    char stringLiteral[]="hello world";
    

    The only difference between contents of first array and second string is that second string's got a null character at its end.

    When it's the matter of initializing a char array, is there a macro or something that allows us to put our initializing text between two double quotation marks but where the array doesn't get an extra null terminating character?

    It just doesn't make sense to me that when a terminating null character is not needed, we should use syntax of first mentioned initialization and write two single quotation marks for each character in the initializer text, as well as virgule marks to separate characters.

    I should add that when I want to have a char array, it should also be obvious that I don't want to use it with functions that rely on string literals along with the fact that none of features in which using string literals results, is into my consideration.

    I'm thankful for your answers.

  • torak
    torak almost 14 years
    Actually, I don't beleive the second case is initialising a pointer to a character string. Its creating an array and initialising its contents based on the content of the string. And yes the difference really does matter.
  • Pooria
    Pooria almost 14 years
    i think your method should be as efficient as compiler's one for char arrays with automatic storage class, but for char arrays with static storage class or the ones in global scope i think there's no run-time copying done by compiler.
  • Michael Burr
    Michael Burr almost 14 years
    @garrett2011: that's likely true for const char[] items, but I think that most often non-const arrays will have their initial values copied from the program image 'text' (which is non-writable on most platforms) into RAM before main() is invoked. As long as the memcpy() is done only once, efficiency wise it's pretty much six of one, half dozen of the other whether it's done by the runtime or your code.
  • Pooria
    Pooria almost 14 years
    never noticed the "separate character initializers" concept, thanks
  • DevSolar
    DevSolar almost 14 years
    Make sure to splatter some comments around that construct. As you might have guessed already by other answers and comments, not having a terminating '\0' is a rather unusual concept and should come with the appropriate warning signs.
  • Admin
    Admin over 13 years
    I just find your answer a bit confusing. char c[4] = "foo"; does put the null character right? Is this still the poor coding style referred to? How about char[128] = "";? Only initializing a buffer? Is that all right? Or is char[128] = { '\0' }; better?
  • user3437460
    user3437460 almost 8 years
    According to the reference book by Randal Albert, char c[4] = "foo"; does place a null character for you and according to the book it is recommended to write it as char[4] = "foo";. char c[3] = "foo"; is illegal because we need to reserve a space for the terminating null character at the back.
  • Johannes Schaub - litb
    Johannes Schaub - litb almost 8 years
    @user worth reading my entire answer which says "The arrays must be declared one element bigger to contain the string terminating ’\0’."