Sign in to follow this  
xeddiex

Array and pointer question

Recommended Posts

Array names and Pointers are alike(?) Why can't you do this:
	char *name = "dog";
	name[0] = 'c';
	name[1] = 'a';
	name[2] = 't';
	name[3] = '\0';
        *Compiles fine but program crashes*

	//But can do this
	char name[4] = "dog";
	
	name[0] = 'c';
	name[1] = 'a';
	name[2] = 't';
	name[3] = '\0';

Also, True or Not: char *name = "dog";.. Allocates memory for name and then assigns the string "dog" so that means, later on I would have to free(name) because it was dynamically allocated. Or is it not dynamically allocated?

Share this post


Link to post
Share on other sites
No, you do not have to free the char *, simply because you did not use malloc(). It is not dynamically allocated, the compiler knows ahead of time the proper size and thus it is exactly the same as char [3]. This also applies to the null termination you are attempting. The compiler allocates enough space for "dog", but not for the null character, so yes, it will compile, but it will be a segmentation fault because you are reaching into memory that has not been allocated for use with that char *.

Hope that helped.

Share this post


Link to post
Share on other sites
In addition to what Alex said ...

Sytactically pointers and arrays are exactly the same. The only difference is that an array is a const pointer; you cannot reassign an array to point to a different location.

int* pointer;
int array[10];

pointer = array; /* okay */
array = pointer; /* ERROR!!! */

EDIT: After reviewing the original post, I realize my post has absolutely nothing to do with the question. Please ignore.

Share this post


Link to post
Share on other sites
char* is just a pointer...

new char[x]

reserves x memory at a pointer address dynamically. which you would have to

delete []

... later or you'll have a memory leak. Note the [] after delete - it's important when removing dynamic arrays.


When you do
char name[4] = "dog";

It's creating an automatic array of 4 and initalising each element with the string. Automatic variables delete themselves when they fall out of scope.



All array handles are pointers to memory - the first element of a contigous set of memory. Thus name+1 == 'o'

Share this post


Link to post
Share on other sites
The first example sets a pointer to your program's string table, which is arbitrarily stored (ie, you can't make any guarantees as to how or where they're stored; we usually expect it to be hard-coded at the top of the executable). You're overstepping the protected bounds of your own program, which is why you get the access violation.

Share this post


Link to post
Share on other sites
char *name means you create "an pointer to an char".

when you do:
char *name = "dog" you kind of create an array[] = { 'd', 'o', 'g' } and assign the adress of that array to name.

char name[4] = "dog"; is wrong .... but

char name[] = { 'd', 'o', 'g' }; is legal

char name[13] = { 0 }; will set 0 in every space of array.

using new and delete.

char *name = new char[ "dog" ];

delete [] name;

think thats right

Share this post


Link to post
Share on other sites
Quote:
Original post by DarkSlayer
think thats right
It's not. char *name = "dog"; doesn't create an array at all. It initializes a pointer to a static string literal. If you open up the binary in a hex editor, you'll actually see the string in there. char name[4] = "dog"; is correct; it initializes the elements of the array to 'd', 'o', 'g' and '\0'.

char name[] = { 'd', 'o', 'g' }; creates an undimensioned array, which is equivalent, believe it or not, to char *name = { 'd', 'o', 'g'}; and almost equivalent to char *name = "dog"; The difference? The former doesn't terminate in a null, meaning that you can't print the array as it will lead to an access violation.

There's a bad habit around here of not reading previous posters' comments, causing people to reiterate wrong answers.

Share this post


Link to post
Share on other sites
Quote:
Original post by Oluseyi
char name[] = { 'd', 'o', 'g' }; creates an undimensioned array, which is equivalent, believe it or not, to char *name = { 'd', 'o', 'g'}; and almost equivalent to char *name = "dog"; The difference? The former doesn't terminate in a null, meaning that you can't print the array as it will lead to an access violation.

Actually, char name[] = { 'd', 'o', 'g' }; is equivalent to char name[3] = { 'd', 'o', 'g' };

Quote:
Original post by Oluseyi
There's a bad habit around here of not reading previous posters' comments, causing people to reiterate wrong answers.

Yeah, I notice people doing that a lot in other threads lately as well.

Edit: Also, technically he is correct that an array is created -- the type of a string literal in C++ is a const char array of the appropriate length. It's just that the array isn't managed by the scope of its use. As well, to DarkSlayer, char *name = new char[ "dog" ]; is not valid. You need to allocate the space for the array and copy the values in (or use a compiler extension).

Share this post


Link to post
Share on other sites
Quote:
The first example sets a pointer to your program's string table, which is arbitrarily stored (ie, you can't make any guarantees as to how or where they're stored; we usually expect it to be hard-coded at the top of the executable). You're overstepping the protected bounds of your own program, which is why you get the access violation.


...Here's where we're getting somewhere. I undertstand that char* name, is just a pointer that' can hold "only" address's...
Such as and only the first address of a char of a string and the rest are stored one by one contigiously to form a string.
That I get. What get's me confused is when working with pointers and arrays. Oluseyi, said what I was looking for but I don't quite get how I'm "overstepping the protected bounds of your own program", could you elaborate a little bit more on this please? It would also be very helpful "if" you could somehow do a little diagram showing how it works.

Thanks everyone for your input. If you have anything else to add, please do so.


Share this post


Link to post
Share on other sites
Quote:
Original post by xeddiex
Quote:
The first example sets a pointer to your program's string table, which is arbitrarily stored (ie, you can't make any guarantees as to how or where they're stored; we usually expect it to be hard-coded at the top of the executable). You're overstepping the protected bounds of your own program, which is why you get the access violation.


...Here's where we're getting somewhere. I undertstand that char* name, is just a pointer that' can hold "only" address's...
Such as and only the first address of a char of a string and the rest are stored one by one contigiously to form a string.
That I get. What get's me confused is when working with pointers and arrays. Oluseyi, said what I was looking for but I don't quite get how I'm "overstepping the protected bounds of your own program", could you elaborate a little bit more on this please? It would also be very helpful "if" you could somehow do a little diagram showing how it works.

Thanks everyone for your input. If you have anything else to add, please do so.



Your program is given a very specific part of memory. This memory is for your program only, and is given by the OS. This set of memory is entirely based off of the variables you declare and use. When you dynamically allocate memory, you are asking the OS for more memory. When you use char * str = "dog" hard-coded, the compiler notices this, and puts in char str[3] = "dog" (in essence).

What this means is, you have only been allocated a set amount, and when you try to run the program, you are reaching beyond this line into some other program's memory (maybe no other program..but can be). The OS won't let that happen, so it crashes.

The above is different than char str[4] = "dog" because now the compiler allocated enough memory for 4 characters (4 bytes), and you are able to put the null character on the end. Before, the compiler allocated 3 bytes and you were trying to reach for a fourth, which was not your program's memory, thus the error.

Share this post


Link to post
Share on other sites
No no no, this isn't an issue of accessing unallocated memory. Oluseyi already said it:

Quote:

The first example sets a pointer to your program's string table, which is arbitrarily stored (ie, you can't make any guarantees as to how or where they're stored; we usually expect it to be hard-coded at the top of the executable).


The string is in the executable, along with the rest of the application's code (which is in the form of x86 assembly code). Windows doesn't let you change the executable's data while you are actually running that executable (which is not an unreasonable rule).

And as was stated, it's a platform-specific thing. I've worked on platforms where you are allowed to modify string literals. (It's still a bad thing to do, though).

Share this post


Link to post
Share on other sites
After careful reading I came to the conclusion that...
You cannot change char *str = "dog" (str[1] = 'x';) because the string is a "static" string literal.

Correct?

Share this post


Link to post
Share on other sites
Yes! That is correct.

char *str = "dog"; /* perfectly legal */
str[0] = 'c'; /* Illegal */

I am sure here where your program crashes because char *str is actually treated as const char *str. The only way you can change the contents is by copying it into a new "array".

That is it!

Share this post


Link to post
Share on other sites
The whole array vs. pointer thing is confusing, and made worse because many tutorials say they're the same thing. My appologies since this has all been covered, but somewhat confusing and piecemeal. Here's my take. Given:

char *string1 = "Doggie";
char string2[7] = "Doggie";
char string3[] = "Doggie";
char string4[6] = "Doggie";
char string5[10] = "Doggie";

Now, string1 is a pointer to a string literal. I believe string literals are "const char *" in C++ and "char *" in C, but the behavior of modifying a string literal is undefined in both cases. What does this mean? Anything can happen when you try to modify it. In your case, this meant it crashed the program (it was in read only memory). In other cases, if might work fine. In yet other cases, it might cause other problems, like when you modify "Doggie" it also modifies "My Doggie" used elsewhere in the program (overlapping to save space). Do a search for "Death Station 9000" in comp.lang.c for an amusing look at undefined behavior (including nasal demons). Note, sizeof(string1) is likely 4 (that is, a pointer to char takes 4 bytes).

string2 is an array of 7 char's. This is equivalent to writing:
char string2[7] = {'D','o','g','g','i','e','\0'};
Note that initializing this way DOES include the terminating '\0'. sizeof(string2) is 7.

string3 is also an array of 7 char's. The length of the array is determined by the length of the initializer, which is 7 in this case (6 letters + 1 '\0'). This is equivalent to string2, but if you change the string you don't have to worry about changing the size of the array. sizeof(string3) is 7.

string4 is an array of 6 char's. This is equivalent to writing:
char string4[6] = {'D','o','g','g','i','e'};
Note that there is no terminating '\0', so this is not, technically, a string and will only cause problems if you pass it to functions expecting strings. My knowledge fails me on whether it's legal to make string4 an array of less than 6 char (while still initializing it with "Doggie"), but I believe it's legal and will just further truncate the string. sizeof(string4) is 6.

string5 is an array of 10 char's. Again, my knowledge fails me slightly. string5[7], string5[8], and string5[9] are either initialized to 0 (which is the same as '\0') or uninitialized. In any case, they are dead weight unless you intend to use them (string functions won't get passed the first '\0' in the array). sizeof(string5) is 10.

If you really want to understand the whole pointer vs. array thing, understand why sizeof(stringN) is what it is for each N. Keep in mind that sizeof(char) is defined to be 1. If we're talking int's instead of char's, sizeof(string1) will likely stay the same (that is, it will be 4), but all the others will have to be multiplied by sizeof(int) (which is likely equal to 4).

Share this post


Link to post
Share on other sites
If it's like you say
Quote:
Way Walker
"I believe string literals are "const char *" in C++ and "char *" in C, but the behavior of modifying a string literal is undefined in both cases. What does this mean? Anything can happen when you try to modify it. In your case, this meant it crashed the program (it was in read only memory)."


...then, char array[] = "doggie" would be a const string literal too!? If so, then why am I able to change a value of a element of a const string ie. array[3] = 'x'; (string is now, dogxie) /*NO CRASH*/ But can't do that with "char *str = "doggie" then, str[3] = 'x'; /*CRASH*/

I've read all of this: http://www.gamedev.net/reference/articles/article1697.asp and either it does'nt explain it or I'm plain dumb. God this is so messed up cause it's very confusing.

BTW Way Walker, I get the whole other stuff you wrote after the quote I quoted above.

p.s: I hope it's what dimensionX said.

Share this post


Link to post
Share on other sites
Quote:
Original post by xeddiex
If it's like you say
Quote:
Way Walker
"I believe string literals are "const char *" in C++ and "char *" in C, but the behavior of modifying a string literal is undefined in both cases. What does this mean? Anything can happen when you try to modify it. In your case, this meant it crashed the program (it was in read only memory)."


...then, char array[] = "doggie" would be a const string literal too!? If so, then why am I able to change a value of a element of a const string ie. array[3] = 'x'; (string is now, dogxie) /*NO CRASH*/ But can't do that with "char *str = "doggie" then, str[3] = 'x'; /*CRASH*/


In dimensionX's example, you have str with type "char *" which is pointing to a string literal which you should think of as having type "const char *". Modifying something that is const qualified usually produces undefined behavior, even if it's through a non-const pointer.

And I don't think you understood what I was saying, so my appologies for not being clear.
char myStr[] = "doggie";
is the same as doing
char myStr[7] = "doggie";
which means that myStr is an array of 7 elements in both cases. Doing
myStr[3] = 'x';
will change myStr to "dogxie" in both cases. However,
char *myStr = "doggie"; myStr[3] = 'x';
produces undefined behavior because you're modifying the string literal (in your case, this means it crashes).

Hmm... perhaps what's confusing you is the difference between [] when declaring a variable and [] in a prototype list? Consider:

void function1(char arg1[]) {}
void function2(char arg2[7]) {}
void function3(char *arg3) {}
int main(void) {
char var1[] = "doggie";
char var2[7] = "doggie";
char *var3 = "doggie";
return 0;
}



EDIT: arg1 is a pointer to char, arg2 is a pointer to char, arg3 is a pointer to char.
var1 is an array of 7 char, var2 is an array of 7 char, var3 is a pointer to char.

[Edited by - Way Walker on December 2, 2004 2:09:29 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
As numerous people have already pointed out

a) char name[] = "dog";
b) char *name = "dog";

Are fundemantally different. I wont go into the semantics..

But the short explanation is...

a) guarantees that access to the array will be in read/write memory.

b) guarantees nothing the string could end up in read only memory.. you may *sometimes* be able to modify the array other times you will get some form of access violation.


b) On x86 i think [probably wrong here] that the pointed to array ends up in the .DATA segment of the executable along with all other static string constants. ** if someone can put me straight on this i would be grateful **

As for (a) all i can say for certain is that the array will reside in some piece of memory that you can modify.

** AFAIK the best explanation of this and other such topics is by far the C Programming FAQ by Steve Summit



Share this post


Link to post
Share on other sites
Quote:
Original post by Way Walker
arg1 is a pointer to char, arg2 is an array of 7 char, arg3 is a pointer to char.
var1 is an array of 7 char, var2 is an array of 7 char, var3 is a pointer to char.

Actually, in your example, arg2 is a pointer to char as well. The 7 is meaningless.

Share this post


Link to post
Share on other sites
Quote:
Original post by Polymorphic OOP
Quote:
Original post by Way Walker
arg1 is a pointer to char, arg2 is an array of 7 char, arg3 is a pointer to char.
var1 is an array of 7 char, var2 is an array of 7 char, var3 is a pointer to char.

Actually, in your example, arg2 is a pointer to char as well. The 7 is meaningless.


Yes yes, many appologies. I was thinking of
void function2(char arg2[][10]);
or
void function2(char (*arg2)[10]);
which are the solutions to another post from someone having trouble passing a multidimensional array to a function.
EDIT: Yeah, reference to array as well, but I'm used to C, so I don't tend to think of references. Anyway, if you're using C++, why aren't you using a vector or some other container?

Also, C99 has VLA's
void function2(size_t n, char arg2[n]);
which makes sizeof arg2 == n.

Share this post


Link to post
Share on other sites
char *name = "dog";

That only allocates 3 positions (so index 0 - 2 is defined)... and when you put the null terminated thing... it died.

Hope that helps... I don't think it assigns the \0 by default.

Share this post


Link to post
Share on other sites
Quote:

Anonymous Poster
As numerous people have already pointed out

a) char name[] = "dog";
b) char *name = "dog";

Are fundemantally different. I wont go into the semantics..

But the short explanation is...

a) guarantees that access to the array will be in read/write memory.

b) guarantees nothing the string could end up in read only memory.. you may *sometimes* be able to modify the array other times you will get some form of access violation.


And that is the answer I was looking for.
Thanks alot everyone.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this