views:

1370

answers:

6

Hi all..

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

A: 

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 :))

warren
The third example does work, it will point to read-only memory containing the string. However, if you try to change it, you're in trouble.
Graeme Perrow
Guess it depends on your compiler... or the error-level you have set: last time I did #3 it cranked-out a slew of warning and a coupe errors.
warren
Are you sure? it shouldn't.
Leonardo Herrera
#3 warns in GCC with -Wwrite-strings, but that's not included in either -Wall or -Wextra. literal -> non-const char* is deprecated, I think, so a warning is reasonable.
Steve Jessop
I do tend to have my error/warning levels quite high, so this may be behavior I see that isn't default :)
warren
+9  A: 

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.

Timbo
This would make an excellent interview question!
j0rd4n
Wow, I just learned something! I knew about #1 but had never even thought about #2/#3.
Brian
+30  A: 
Johannes Schaub - litb
Very nice answer :) Thank you for your time :)
Meeh
You know, I'd never taken the time myself to understand the complexities of [] array vs pointer declaration. I'd always just used explicit length arrays or pointers. Thanks!
Nick Bedford
A: 

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.

Tyler McHenry
That's not true. Symbols with an initial underscore followed by a capital letter are reserved for the implementation. Underscore followed by lowercase is fine, in C++ at least. I haven't checked the C standard, but it reserves all kinds of stuff, including function names starting with s or w IIRC.
Steve Jessop
Okay, to clear this up the rule seems to be that leading underscores followed by a capital letter are always reserved, and leading underscores followed by a lowercase letter are reserved only in std:: and in the global namespace, so a leading underscore on a member is actually OK.
Tyler McHenry
"reserved only in std:: and ::". I don't quite understand that, since you can't add symbols to std:: anyway (that is, the entire namespace is reserved for the implementation).
Steve Jessop
A: 

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++?

Leonardo Herrera
A: 

Please also take a look at the http://c-faq.com/aryptr/aryptr2.html The C-FAQ might prove to be an interesting read in itself.

SDX2000