Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ strings: [] vs. *

Been thinking, what's the difference between declaring a variable with [] or * ? The way I see it:

char *str = new char[100];
char str2[] = "Hi world!";

.. should be the main difference, though Im unsure if you can do something like

char *str = "Hi all";

.. since the pointer should the reference to a static member, which I don't know if it can?

Anyways, what's really bugging me is knowing the difference between:

void upperCaseString(char *_str) {};
void upperCaseString(char _str[]) {};

So, would be much appreciated if anyone could tell me the difference? I have a hunch that both might be compiled down the same, except in some special cases?

Ty

like image 235
Meeh Avatar asked Nov 21 '08 09:11

Meeh


People also ask

What does char * [] mean in C?

char* is a pointer to a character, which can be the beginning of a C-string. char* and char[] are used for C-string and a string object is used for C++ springs. char[] is an array of characters that can be used to store a C-string.

Should I use char [] or std::string?

In terms of API and standard library everything is implemented in terms of strings and not char[], but there are still lots of functions from the libc that receive char[] so you may need to use it for those, apart from that I would always use std::string.

Is char * A string in C?

This last part of the definition is important: all C-strings are char arrays, but not all char arrays are c-strings. C-strings of this form are called “string literals“: const char * str = "This is a string literal.

Is char * a string?

char is a primitive data type whereas String is a class in java. char represents a single character whereas String can have zero or more characters. So String is an array of chars.


2 Answers

Let's look into it (for the following, note char const and const char are the same in C++):

String literals and char *

"hello" is an array of 6 const characters: char const[6]. As every array, it can convert implicitly to a pointer to its first element: char const * s = "hello"; For compatibility with C code, C++ allows one other conversion, which would be otherwise ill-formed: char * s = "hello"; it removes the const!. This is an exception, to allow that C-ish code to compile, but it is deprecated to make a char * point to a string literal. So what do we have for char * s = "foo"; ?

"foo" -> array-to-pointer -> char const* -> qualification-conversion -> char *. A string literal is read-only, and won't be allocated on the stack. You can freely make a pointer point to them, and return that one from a function, without crashing :).

Initialization of an array using a String literal

Now, what is char s[] = "hello"; ? It's a whole other thing. That will create an array of characters, and fill it with the String "hello". The literal isn't pointed to. Instead it is copied to the character-array. And the array is created on the stack. You cannot validly return a pointer to it from a function.

Array Parameter types.

How can you make your function accept an array as parameter? You just declare your parameter to be an array:

void accept_array(char foo[]); 

but you omit the size. Actually, any size would do it, as it is just ignored: The Standard says that parameters declared in that way will be transformed to be the same as

void accept_array(char * foo);

Excursion: Multi Dimensional Arrays

Substitute char by any type, including arrays itself:

void accept_array(char foo[][10]);

accepts a two-dimensional array, whose last dimension has size 10. The first element of a multi-dimensional array is its first sub-array of the next dimension! Now, let's transform it. It will be a pointer to its first element again. So, actually it will accept a pointer to an array of 10 chars: (remove the [] in head, and then just make a pointer to the type you see in your head then):

void accept_array(char (*foo)[10]);

As arrays implicitly convert to a pointer to their first element, you can just pass an two-dimensional array in it (whose last dimension size is 10), and it will work. Indeed, that's the case for any n-dimensional array, including the special-case of n = 1;

Conclusion

void upperCaseString(char *_str) {}; 

and

void upperCaseString(char _str[]) {};

are the same, as the first is just a pointer to char. But note if you want to pass a String-literal to that (say it doesn't change its argument), then you should change the parameter to char const* _str so you don't do deprecated things.

like image 92
Johannes Schaub - litb Avatar answered Oct 12 '22 23:10

Johannes Schaub - litb


The three different declarations let the pointer point to different memory segments:

char* str = new char[100];

lets str point to the heap.

char str2[] = "Hi world!";

puts the string on the stack.

char* str3 = "Hi world!";

points to the data segment.

The two declarations

void upperCaseString(char *_str) {};
void upperCaseString(char _str[]) {};

are equal, the compiler complains about the function already having a body when you try to declare them in the same scope.

like image 24
Timbo Avatar answered Oct 12 '22 23:10

Timbo