Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C, is it more space efficient to declare a 2 dimensional array of chars or a ragged array of strings? (specific question below)

I have a specific question regarding space efficiency below:

Suppose you want to declare an array of 7 string literals that represent the 7 colors of the rainbow (i.e. red, orange, yellow, green, blue, indigo, and violet). Assuming that the size of a pointer is 8 bytes, is it more efficient space-wise to declare a 2-dimensional array of chars or a ragged array of strings?

Strings in C confuse me and I am not sure I am going about this question the right away. Any help would be greatly appreciated, especially if even a small amount of code is used to demonstrate. Thank you all in advance!

EDIT: I have written the following code:

#include <stdio.h>
#include <string.h>

int main(void) {
    char *string_array[] = {"red", "orange", "yellow", "green", "blue", "indigo", "violet"};
    char char_array[][7] = {"red", "orange", "yellow", "green", "blue", "indigo", "violet"};

    printf("\nThe size of a string is: %lu", sizeof(char *));
    printf("\nThe size of a string array with the given data is: %lu", sizeof(string_array));
    printf("\nThe size of a char is: %lu", sizeof(char));
    printf("\nThe size of a char array with the given data is: %lu", sizeof(char_array));

    return 0;
}

Which outputs the following:

The size of a string is: 4
The size of a string array with the given data is: 28
The size of a char is: 1
The size of a char array with the given data is: 49

I am not sure if I have done this correctly as I expected the first array (ragged array of strings) to be larger?

like image 981
throwaway_bruh Avatar asked Mar 02 '23 12:03

throwaway_bruh


2 Answers

Option 1:

const char *colors = {"red", "orange", "yellow", "green", "blue", "indigo", "violet"};

Here all the strings take up as much read-only memory as they need (43 bytes), however an additional 56 bytes (7 pointers of 8 bytes) are used to store the 7 pointers in memory, resulting in 99 bytes in total.

Option 2:

const char colors[][7] = {"red", "orange", "yellow", "green", "blue", "indigo", "violet"};

Here you declare a 2D array, but since you need to declare the 2nd dimension at compile time, it must be large enough to accommodate the longest string in the array (+1 byte in each string for the null terminating byte). Thus you end up wasting space on all the shorter strings.

Here, 49 bytes (7 strings of 7 bytes) are allocated in total, but in order to store all of the strings you only need 43 bytes - thus 6 bytes are "wasted".


The conclusion

All in all the 2nd option requires less memory.

like image 53
bool3max Avatar answered Mar 05 '23 08:03

bool3max


option 1 and option 2: see bool3max answer.

option 3

char *data = "red\0orange\0yellow\0"
      "green\0blue\0indigo\0violet";
skiprint(data, 3);

with

void skiprint(const char *zs, int n) {
    while (n--) { while (*zs) zs++; zs++; }
    puts(zs);
}

https://ideone.com/vI6wqs

like image 36
pmg Avatar answered Mar 05 '23 09:03

pmg