1

What is the benefit of having an array vs. pointer to char, as in the following structure:

struct my_struct {
   int p;
   char s[10];
};

or

struct my_struct {
   int p;
   const char *s;
};

The one advantage that I'm seeing is that with char * it is easier to distinguish "no string provided" and "empty string provided", also it occupies less space then an array.

Also, in both cases I can initialize:

struct my_struct p { .p = 10, .s = "abcd" };

On the other hand, I can't easily use strncpy() on char *, it has to be valid pointer on the allocated memory.

So, what are the other advantages?

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
Mark
  • 6,052
  • 8
  • 61
  • 129
  • Here's a usual analogy for arrays vs pointers: What is the benefit of having a house address vs. a street? With a house address it is easier to distinguish "no address provided" and "empty lot provided", also it occupies less space than a street. In both cases I can initialize it from a given street. On the other hand, I can't easily put people in my house address, it has to actually be the address of a valid house. – user253751 Mar 28 '18 at 03:51

3 Answers3

2

The advantages and disadvantages depend on the your algorithms and what you are trying to achieve, there is no simple answer to that. What can be said is this:

If the structure has a char array (this is only my opinion):

Advantages

  • You don't need to allocate memory for it, no need to check if malloc fails and no need to free the memory afterwards

  • Easy to use fwrite/fread for an object of your structure, no need to take care of the pointer case where you have to dereference it prior to the write operation / allocate memory prior to the read operation.

  • You can use string literals to initialize it and you can change the contents afterwards.

Disadvantage

  • You have only a limited amount of space, if you need to store a string that is longer than what the array can hold, then you are in trouble and might have to reconsider you design.

If the structure has a char pointer:

Advantages

  • You have more freedom with your pointer, you can allocate and reallocate memory depending on your needs.

  • You can assign the pointer to point to other char arrays without the need of allocation

  • You structures are smaller in size and would need less memory. Great when you are not dynamically allocating memory for your structs.

Disadvantage

  • You need to do memory management yourself, depending on your design, this can consume a lot of your time until you get it right

  • If you plan to send/write objects to the network or hard drive, you need to take care of dereferencing the pointer, you cannot do fwrite(obj, n, sizeof *obj, fp), you have to do in many steps.

  • If you assign a string literal, you have to be careful not to modify it later on. Modifying a string literal is undefined behaviour and in most systems you'll get a segfault right away.

In general think about the design of your own software and also on your needs, then you can weight the pros and cons and use the one that fits best to your project.


I can't easily use strncpy() on char*, it has to be valid pointer on the allocated memory.

That's only partially right, once memory has been allocated, you can use strncpy.

Also, in both cases I can initialize:

struct my_struct p { .p = 10, .s = "abcd" };

Yes, but in the case of an array, the array is filled with the contents of the string literal and can be modified later on. In case of the pointer, it will point to the string literal and like I said before, if your algorithm needs to modify the contents, then you cannot use strings literals.

Pablo
  • 13,271
  • 4
  • 39
  • 59
  • 1
    Other Advantage with `char s[10];` structures of that type can be assigned, e.g. `struct my_struct p { .p = 10, .s = "abcd" }, pb; pb = p;`, with a pointer - a deep copy would be required to duplicate. – David C. Rankin Mar 28 '18 at 03:33
1

Let me try to explain it simple:

Arrays are simpler to use but harder to manipulate.

Pointers you can easily free space you already have allocated for char* and allocate new space, thus having more flexibility. Lets look at one example:

int cnt = 0; // holds number of characters enterd
char c = 0;
while (cnt != -1) {
  printf("Enter number of characters in next word: ");
  cnt = getint();
  printf("Enter the word: ");
  char *word = malloc((cnt + 1) * sizeof(char));
  int i = 0;
  char c = 0;
  for (;i < cnt; ++i) {
     *(word + i) = c; // *(word + i) is technically the same as word[i]
  }   
  *(word + i) = '\0';
  free (word);
} 

You see in above example you can allocate as much space as you need at given time, which you cannot do with array.

So if you are making English dictionary, with array you would need to allocate 45 character right away even though average word length is 5, 6 characters long.

Applying it to your case

struct my_struct {
  int p;
  char s[10];
};

would have to take at most 10 characters which is allocated at the start of the program. If you enter 2 characters you 8 are basically wasted. Where in

struct my_struct {
  int p;
  char *s;
};

you can call malloc() you can allocate 1 character and it will hold 1 character no wasted space at all, and you can allocate 100 characters and it will hold 100. All of this would be on the fly.

0

also it occupies less space then an array.

It doesn't, since you will have to point to some data anyway. Assuming you point to a buffer of the same size, you end up with sizeof(void *) + sizeof(char [10]) in total.

Also, in both cases I can initialize:

struct my_struct p { .p = 10, .s = "abcd" };

Yes, because the compiler is setting up the literal string in memory and pointing the s member to it. In this case, you are using sizeof(void *) + sizeof(char [5]) bytes in total.

I can't easily use strncpy() on char *, it has to be valid pointer on the allocated memory.

No, you can use strncpy() in both cases.


Regarding what you should use: the choice is not so much about advantages and disadvantages. Instead, you should use whatever you need. For instance, if you don't know in advance the maximum size of the array, you have no choice but to go for the pointer approach. If you do know, then you can use both approaches; but the array one will be simpler to maintain.

Performance considerations can also influence your decisions. For instance, assuming you operate on many instances of the struct, it depends on how you are accessing the struct and the kind of data structure you are using to hold the instances, i.e. the access patterns to the data. Many times an embedded array is faster, but not always.

Acorn
  • 24,970
  • 5
  • 40
  • 69
  • Somewhat a tight one here on occupying less space. `char *p` 8-bytes on x86_64, `char s[10];` is 10-bytes anywhere. If the string + *nul-char* was less than 8-bytes -- the pointer would actually require more memory than the array. But in the general sense, you are correct. – David C. Rankin Mar 28 '18 at 03:30
  • @DavidC.Rankin: the `struct` itself, yes, of course; but assuming he still needs the same memory somewhere else (i.e. a string of 10 bytes), then it is always strictly more (this is what I meant by `sizeof(void *) + sizeof(char [10])`). Also, if he points to dynamically allocated memory, then we need to add `malloc`'s overhead. – Acorn Mar 28 '18 at 09:07