C: How to declare an array of strings correctly?

I saw both:

const char* arr = {"foo", "bar"}; 

and

 const char* arr[] = {"foo", "bar"}; 

What is the correct and usually standard way?

What is the difference between the two?

What's the difference between

  const char**arr = {"foo", "bar"}; 

and

  const char* arr[] = {"foo", "bar"}; 

and

  const char* * const arr = {"foo", "bar"}; 

and

  const char* const * const arr = {"foo", "bar"}; 

Sorry for so many questions, just trying to figure it out better ...

+4
source share
4 answers

Regarding the constant ...

 const char* constValue = "foo"; constValue = "bar"; constValue[0] = 'x'; // will not work char* const constPtr = "foo"; constPtr = "bar"; // will not work constPtr[0] = 'x'; const char* const arr[] = { "foo", "bar", 0 }; // all const 

'const char * const' is often the best solution for something completely permanent. Another optimization would also be to make this static if it is declared in the local scope. 0 ptr is useful for a reference value.

+2
source

This is not true since it does not have the right level of indirection.

 const char* arr = {"foo", "bar"}; 

This is not true because = missing. This is a bit like a function definition.

 const char* arr[] {"foo", "bar"}; 

This is the usual regular form.

 const char* arr[] = { "foo", "bar" }; 

Edit

You cannot initialize a pointer from an aggregate initializer (ie {..., ..., ...}). You can do as

 const char* str1 = "A string"; 

and

 const char str2[] = "Another string"; 

but it is different.

The string literal is of type "array n char", so it can be converted to a pointer, while the initialization list is not really an array, it's just a way to initialize arrays.

+10
source

There are several approaches. The simplest thing is to declare an array of char arrays, for example:

 char strs[N][M + 1]; // M is max length of each string ... strcpy(strs[i], "foo"); 

All memory for the strings is statically allocated, but the size of each row in the array is fixed, and you must have the size for the longest string, which can lead to some internal fragmentation. All lines are writable.

Another approach is to declare an array of pointers to char:

 char *strs[N]; ... strs[i] = malloc(strlen("bar") + 1); if (strs[i]) strcpy(strs[i], "bar"); 

This way you can allocate as much or less memory as each row in the array requires, and if necessary, you can resize your rows. You can also point to string literals, but remember that literals may not be writable; that is, you cannot do something like:

 strs[j] = "foo"; strs[j][0] = 'b'; // may not be allowed on string literal 

You can dynamically distribute the whole breakdown:

 char **strs = malloc(sizeof *strs * N); for (i = 0; i < N; i++) strs[i] = malloc(SIZE + 1); 

This approach allows not only to resize each row as needed, but also to resize rows. Note that in this case, strs is not an array type, although it is treated as an array.

Note that the best methods regarding malloc () are different between C and C ++. In C, he considered bad practice to produce the result of malloc (). Firstly, this is not necessary since void pointers are implicitly thrown into other types of object pointers. For another, it will overwhelm diagnostics if you forget to # include stdlib.h or otherwise don't have a prototype for malloc () in scope. Remember that if C does not see the prototype of the function before the link, it will assume that the function returns an int, which cannot be implicitly converted to a pointer type.

+1
source

As a rule, I use dynamic memory, if possible. I find it easier to think about pointers than to fight with an array type.

 //Allocate pointers for the strings char **c = (char**)malloc(maxnumofstrs*sizeof(int)); //allocate memory for each string for(int i = 0; i < maxnumofstrs; i++) { c[i] = (char*)malloc(maxwidth); } 
0
source

All Articles