tags:

views:

918

answers:

5

Are these two equivalent?

char * aString = "This is a string.";

char aString[] = "This is a string.";

From my understanding, C++ stores strings by their addresses, so the pointer is getting a valid address. I assume the strings are also stored as type char? But how does it know how much memory to allocate for the string? Normally, char arrays need their array size preset. I believe the [] type arrays are counted by the compiler before compilation. Is this what happens for the string literal pointer as well?

On to my second question, what is the difference between these two:

int someNumber;

int * someNumber = new int;

The second is supposed to be dynamic allocation. If I understand the concept right, it allocates the memory as soon as it reads the declaration. But what happens in the standard declaration? Basically, I need to understand how dynamic allocation is advantageous over standard declarations.

A: 

Yes, in C language type *foo is equivalent to type foo[].

Static variables are allocated at load-time on the data segment, whereas dynamic variables are allocated at run time on the stack.

Aif
See comments on posting: http://stackoverflow.com/questions/406010/passing-pointer-to-an-array-of-arrays-through-function#406032
Mr.Ree
A: 

For your first question the compiler counts the number of characters in a string and creates an array of that size. char *theString="hello"; creates a char array on the heap. char []theString="hello"; creates that array on the stack. For your second question int *thenum=new in; is dynamic. Standard declarations store there data on the stack which means memory doesn't have to be allocated. Memory allocation can be a slow process especially when the heap is fragmented. Stack space is limited though, so the general rule is use dynamic allocation when you need a lot of memory or have a data structure requiring pointers, use standard allocation when you just need a variable or small object.

Jared
@Brian R. Bondy: It might be useful to state *why* the answer is incorrect.
Greg Hewgill
char *theString="hello" does not create an array on the heap. It puts the array into the data segment with all the other static data.
Wilka
char *theString="hello" -- With some compilers/OS's, that's put into a READ-ONLY data segment. A common gotcha for new programmers.
Mr.Ree
+15  A: 
char * aString = "This is a string.";

It's making a pointer aString point to a statically allocated char array containing "This is a string.". The string is not writable, even though the type of the pointer might suggest you could write to it. See the answer in the link below, for reasons to avoid it and how you can do better.

char aString[] = "This is a string.";

It's creating an array having the type char[18]. Even though you tell it with the declarator that aString has a type char[], it's really defining an array with a complete type - that is, with a defined length for that array. That's because it's directly initialized, and the compiler can deduce the size of the array. The array is writable. You can freely change characters in it. I tried to make the difference clear in this answer: http://stackoverflow.com/questions/308279/c-vs#308724

int someNumber;

It's an integer variable created on the stack. It's not initialized. It has automatic storage duration: Going out of scope (returning from the function, breaking out of the loop...) will free the memory of it. You can of course write to it as much as you want.

int * someNumber = new int;

It's a pointer which will point to an integer that's dynamically allocated. The int is not initialized. And the memory is not freed when the pointer goes out of scope. That is, when your function returns, the memory will still be there.

Johannes Schaub - litb
For your first answer, it could also be noted that only one choice allows aString to be REassigned.
Shmoopty
+5  A: 
char *aString = "This is a string.";

Declares a pointer to a character string. That is, a pointer to the area of data segment memory where this string is defined.

char aString[] = "This is a string.";

Declares a character array on the stack and copies the contents of the string into it. As with all stack allocations, you can not return the variable from function.

int someNumber;

Is an integer declared on the stack.

int *someNumber = new int;

The "new int" creates a dynamic allocation on the heap. And the "int *someNumber =" assigns the address to a pointer to an integer.

For dynamic allocations you need to remember to call delete when finished to allow the heap to recover the memory or use a smart pointer or similar.

Simon Brangwin
+1  A: 

There are a few unclear things in the correct answers. While char foo[] = "literal"; does create a writable array of text, each time the function starts, the text it reset:

void func() {
    char foo[] = "hello";

    cout << foo << endl;

    foo[2] = 'w';
    foo[3] = 'w';

    cout << foo << endl;
}

func();
func();

If you run that you will get:

hello
hewwo
hello
hewwo

The string literal "hello" is stored in the data segment of the application and when func reaches the statement declaring foo, it copies the string from the data segment onto the stack.

On the other hand char* foo = "hello"; is illegal since "hello" is a const lvalue. You would need to declare it const char* foo = "hello";. This creates a pointer directly to the data stored in the programs data segment and writing to that data is undefined.

If you cast away the constness you can write to it.

void func() {
    const char* c_foo = "hello";
    char* foo = const_cast<char*>(c_foo);

    cout << foo << endl;

    foo[2] = 'w';
    foo[3] = 'w';

    cout << foo << endl;
}

hello
hewwo
hewwo
hewwo

Most likely, you would see hewwo on all subsequent calls to func() as shown above. However, with modern multiprocessing operating systems, if the program runs long enough it could be swapped out of memory and when it is swapped back in, the data segment containing the "hello" string would be read from the program's executable on disk and the very next call to func might print hello hewwo or even hello hello or hello hewlo or hewwo hello or any other combination you can think of since time slices could occur at any point during your execution.

Hopefully that isn't too confusing.

jmucchiello
Good points.Actually C++ allows char* foo = "hello". It's a special case where the compiler implicitly const casts the const string literal to nonconst. Try it if you don't believe me :)
Simon Brangwin
I meant to but didn't have the chance at work today. And besides, just because the compiler is lax in one place doesn't mean we should be lax there too. Put the const qualifier in its proper place!
jmucchiello
Yes I agree, much better to use it const char*.Not sure if this exception is in the standard or just a relaxation by compilers. I suspect it's in the standard. I believe the reason for it was so that the millions of existing C programs with char *str = "blah" would be easier to migrate to C++.
Simon Brangwin