Francesco Piraneo G.
Francesco Piraneo G.

Reputation: 870

String array initialization in C

In C it's possible to initialize a string array with such line of code:

char *exStr[] = { "Zorro", "Alex", "Celine", "Bill", "Forest", "Dexter" };

On my debugger the array is initialized as below:

Debugger view

This is different as standard two-dimensional array where each string occupy the same amount of byte; can someone point me on the right direction to understand:

  1. What's means exactly the declaration "char *exStr[] = ...";
  2. How can I re-create the same variable's structure from my program.

Upvotes: 1

Views: 11580

Answers (4)

riverhorse
riverhorse

Reputation: 186

1. As the other answers and comments said, the expression "char *exStr[]" means "array of pointers to char".

a) How to read it

The best way to read it (as well as other more complex C declarations) is to start at the thing's name (in this case "exStr") and work your way towards the extremities of the declaration, like this:

  • First go right, adding each encountered meaningful symbol(s) to the meaning of the expression
  • Stop going right at the first closing paranthesis ")", or when the expression ends
  • When you cannot go right anymore, resume where you started and go left, again adding each encountered symbol to the meaning of the expression
  • Stop going left at the paranthesis "(" that corresponds to the ")" that stopped you on the right, or at the beginning of the expression
  • When stopped going left at a "(" paranthethis and you haven't reached the beginning of the expression, resume going right immediately after the ")" that corresponds to it
  • Keep going right and left until you reach the margins of the expression both ways

In your case, you would go like that:

  • start at exStr: that's the variable's name
  • go right: []: exStr is an array
  • go right: stop: there's nothing there, the "=" sign stops us
  • go left: *: exStr is an array of pointers
  • go left: char: exStr is an array of pointers to char
  • go left: stop: there's nothing there, the "=" sign stops us

b) Why are you seeing that each array element occupies a different amount of bytes

When you have a value like "Zorro", it's a C string.
A C string is an array of bytes that starts at a given address in memory and ends with 0. In case of "Zorro" it will occupy 6 bytes: 5 for the string, the 6th for the 0.

You have several ways of creating C strings. A few common ones are:
A) use it literally, such as:

printf("Zorro");

B) use it literraly but store it in a variable:

char *x = "Zorro";

C) allocate it dynamically and copy data into it

size_t n = 2;
char *p = malloc((n+1) * sizeof(char));
char c = getch(); // read a character from the console
p[0] = c;
p[1] = 0;
// do something with p...
free(p);

Whenever you're putting a string value like "Zorro" in your program, the compiler will reserve memory for just enough to hold this string plus the 0 terminator. It will initialize this memory with whatever you provided inside "", it will add the 0, and secretly keep a pointer to that memory. It will prevent you from modifying that memory (you cannot change that string).
In your code sample, it did this for every string that appeared in the exStr initialization.
That's why you see each array element occupying a different amount of memory. If you look closer to your debugger output, you'll see that the compiler reserved memory for a string immediately after the preceding one, and each string occupies its length in bytes plus the 0 terminator. E.g. "Zorro" starts at 02f, and occupies positions 02f - 034, which are 6 bytes (5 for Zorro and 1 for the 0 terminator). Then "Alex" starts at 035, occupies 5 bytes: 035 - 039, and so on.

2. To create a similar array programmatically:

If all you have are some static strings like in your example, then your code sample is good enough.

Otherwise if you plan to put dynamic values into your array (or if you plan to change the original strings in the program), you would do something like:

#define COUNT 5
char *strings[COUNT];
int i;
for (i = 0; i < COUNT; i++) {
    int n = 32; // or some other suitable maximum value, or even a computed value
    strings[i] = malloc((n+1) * sizeof(char));
    // put up to 32 arbitrary characters into strings[i], e.g. read from a file or from console; don't forget to add the 0 terminator
}
// use strings...
// free memory for the strings when done
for (i = 0; i < COUNT; i++) {
    free(strings[i]);
}

Upvotes: 3

artyom_ban
artyom_ban

Reputation: 121

What's means exactly the declaration "char *exStr[] = ...";

It means 'array of poniter to char'. Char data of literals like "Zorro" are usually placed in read-only data segments, and array elements inlcude only address of the first char of literal.

How can I re-create the same variable's structure from my program.

You can do something like:

char zorro[] = {'Z', 'o', 'r', 'r', 'o', '\0'}; // initialized every char for clarity
char alex[] = "Alex";
char celine[] = "Celine";
...
char* exStr[] = {
    &zorro[0], // explicitly referenced for clarity
    alex,
    celine,
    ...
};

Upvotes: 5

Sourav Ghosh
Sourav Ghosh

Reputation: 134286

What's means exactly the declaration "char *exStr[] = {......};

Here, exStr is an array of char pointers, initialized by the supplied brace enclosed initializers.

To elaborate, the starting address of each string literal in the initializer list is stored into each element of the array.

Point to note, the contents of the array elements (being string literals) are not modifiable.

Regarding the second part,

How can I re-create the same variable's structure from my program.

is not clear. Can you elaborate on that part?

Just in case, if you meant how to access, then, it's just like the normal array access. As long as you're within bounds, you're good to go.

Upvotes: 2

4386427
4386427

Reputation: 44266

For the second part of your question, I guess you are asking for an array of pointers to variable length strings.

It can be done like this:

#include <stdio.h>

int main(void) {
    char* ma[2];   // Array of char pointers for pointing to char-strings

    char* pZorro = "Zorro";         // Char string - not modifiable
    char AlexString[5] = {"Alex"};  // Char string - modifiable

    ma[0] = pZorro;      // Make the first pointer point to the "Zorro" string
    ma[1] = AlexString;  // Make the second pointer point to the "Alex" string

    printf("%s\n", ma[0]);
    printf("%s\n", ma[1]);

    // strcpy(ma[0], "x");   // Run time error! Can't change "Zorro"
    strcpy(ma[1], "x");      // OK to change "Alex"

    printf("%s\n", ma[0]);
    printf("%s\n", ma[1]);

    return 0;
}

The output will be:

Zorro
Alex
Zorro
x

Upvotes: 0

Related Questions