0

Is there any situations where one type is preferred over the other?

The only thing I can think of is...

a pointer uses 4 bytes, and a char array's size depends on the length of the string, so if you have a really big string,it's beneficial to use a char pointer instead in order save memory example: if your passing strings around through arguments.

but in terms of string manipulation, which is preferred?

example:

char *hello_pointer = malloc(sizeof(char) * 20);
char hello_array[20];

strcat(hello_pointer, "hello pointer");
strcat(hello_array, "hello array");

is there a preference for one over the other in this case?

Jules
  • 423
  • 3
  • 11
  • 2
    Prefer using a `std::string`. – Eljay Apr 21 '20 at 21:43
  • 3
    Does this answer your question? [Difference between using character pointers and character arrays](https://stackoverflow.com/questions/1807530/difference-between-using-character-pointers-and-character-arrays) –  Apr 21 '20 at 21:43
  • 1
    It depends entirely on what you're doing. Here you're missing something either way because you're concatenating with uninitialized strings. – Thomas Jager Apr 21 '20 at 21:44
  • On any computer made since 2012 a pointer will be 8 bytes, but that doesn't matter since that same computer surely has several gigabytes of memory. – tadman Apr 21 '20 at 21:44
  • 2
    Please pick either C or C++. They are different languages and the best answer may depend on which language you are actually using. – kaylum Apr 21 '20 at 21:45
  • @Jules "so if you have a really big string,it's beneficial to use a char pointer instead in order save memory" A question arises where will the big string stored?:) – Vlad from Moscow Apr 21 '20 at 21:45
  • _so if you have a really big string,it's beneficial to use a char pointer instead in order save memory_: IMO yes, it seems a good idea: not to waste the stack especially in programs that make intensive use of recursion, e.g.: an interpreter. – David Ranieri Apr 21 '20 at 21:49
  • Unrelated, but: `sizeof char` is always 1 by definition (the sizes are in units of 1 `char`), so multiplying by `sizeof(char)` is unnecessary. If you wish to have the multiplication there for consistency or whatever, rather use the pattern `p = malloc(sizeof(*p) * count)` so that you don't repeat the type. – Arkku Apr 21 '20 at 22:14

2 Answers2

1

This isn't about "saving memory", this is about dynamic allocation versus a fixed-length buffer.

In your example you're assuming that your data will be no more than 19 characters. This could be a huge mistake. The difference between char* x and char x[20] is not really relevant until you want to use that data outside the scope it was declared in.

A char* x allocated using malloc will persist outside the function's scope. A char[20] will not, you need to copy it before it gets recycled.

So in comparison, a buffer like char x[20]:

  • effectively zero cost to create
  • must be conservatively sized to avoid consuming too much stack space
  • will need to be NUL terminated when declared, like char x[20] = { 0 }
  • cannot be used once they fall out of function scope

Whereas char* x:

  • has a small initialization cost
  • must be released with free when no longer used or program will leak memory
  • can be used outside of function scope
  • must be initialized before use, may contain junk data

You're 100% responsible for:

  • properly initializing your character buffers
  • ensuring that the buffers are the correct size for the data you intend to store in them
  • informing any functions manipulating this buffer what the buffer's size is, or in some cases, what the remaining size is
  • NUL terminating any buffers you manipulate where you may overwrite the terminator
  • releasing any memory allocated dynamically

Typically you'll see fixed-length buffers used for things like reading in and parsing a file where you do so carefully and with awareness of your buffer's size limits. Reading functions that take a length argument are the ones you want to use even though there are some like gets() which are commonly shown. Those can and will create huge buffer-overflow bugs.

In C++ it's easy to avoid this mess and just use std::string which deals with all of this for you automatically.

tadman
  • 208,517
  • 23
  • 234
  • 262
  • I see. so its usage really depends on the kind of scope you need? – Jules Apr 21 '20 at 21:54
  • 1
    Exactly. If you want it temporarily, use an array, as these are basically zero cost. If you want it for longer, dynamically. Exception: If you need a buffer of non-trivial size (e.g. over 1024 bytes) use dynamic allocation as stack space is limited. – tadman Apr 21 '20 at 21:55
  • got it. Thank you! – Jules Apr 21 '20 at 21:57
1

Difference is that with malloc() or new you will get memory allocated on the heap and this is slower and will not get destroyed with the end of the scope. char hello_array[20] will be allocated on the stack and will be removed with the stack frame.

Also, with malloc(sizeof(char) * 20) you don't just allocate one pointer but memory block to handle 20 chars. Size will be the same.

mlc
  • 415
  • 3
  • 7