简体   繁体   中英

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

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.

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.

Okay, I had left two negative comments. That's not really useful; I've removed them.

  • The following code initializes a char pointer, pointing to the start of a dynamically allocated memory portion (in the heap.)

char *str = new char[100];

This block can be freed using delete [] .

  • The following code creates a char array in the stack, initialized to the value specified by a string literal.

char [] str2 = "Hi world!";

This array can be modified without problems, which is nice. So


str2[0] = 'N';
cout << str2;

should print Ni world! to the standard output, making certain knights feel very uncomfortable.

  • The following code creates a char pointer in the stack, pointing to a string literal ... The pointer can be reassigned without problems, but the pointed block cannot be modified (this is undefined behavior; it segfaults under Linux, for example.)

char *str = "Hi all";
str[0] = 'N'; // ERROR!
  • The following two declarations

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

look the same to me , and in your case (you want to uppercase a string in place) it really doesn't matters.

However, all this begs the question: why are you using char * to express strings in C++?

As a supplement to the answers already given, you should read through the C FAQ regarding arrays vs. pointers . Yes it's a C FAQ and not a C++ FAQ, but there's little substantial difference between the two languages in this area.

Also, as a side note, avoid naming your variables with a leading underscore. That's reserved for symbols defined by the compiler and standard library.

另请参阅http://c-faq.com/aryptr/aryptr2.html.C-FAQ可能本身就是一本有趣的读物。

The first option dynamically allocates 100 bytes.

The second option statically allocates 10 bytes (9 for the string + nul character).

Your third example shouldn't work - you're trying to statically-fill a dynamic item.

As to the upperCaseString() question, once the C-string has been allocated and defined, you can iterate through it either by array indexing or by pointer notation, because an array is really just a convenient way to wrap pointer arithmetic in C.


(That's the simple answer - I expect someone else will have the authoritative, complicated answer out of the spec :))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM