Diferences between array and pointer initialized strings in C

Member
Posts: 185
Joined: 2005.02
Post: #1
Ok, I just read the section in my C book on String initialization.
I understand that there are to ways two initialize them, as arrays of chars and as pointers. However I am alittle hazy on the differences.
Using the pointer method it is more memory efficient( the ragged array thing), but using it does not allow you to ever change the string, right?
So I would use the pointer method for strings that are permanent, and the array method for strings that may need to be changed?
Quote this message in a reply
Member
Posts: 201
Joined: 2002.06
Post: #2
Both ways are implemented the same as far as I know, so neither has more restrictions or optimization. You should be able to modify the string at will either way as long as there is enough memory allocated. The following two lines do the same thing:

Code:
aString[3] = 'a'
*(aString + 3) = 'a'

I'm actually not really sure where you got the notion that you wouldn't be able to modify a string using one of the two methods, so I apologize if I made a wrong assumption somewhere.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #3
"......." returns a const char *, which may be stored in read-only memory, and therefore not be modifiable.
Quote this message in a reply
Member
Posts: 185
Joined: 2005.02
Post: #4
ooh, so either way double quotation marks makes it unmodifiable? And single quotations for both is modifiable?
Quote this message in a reply
Member
Posts: 114
Joined: 2005.03
Post: #5
No, single quotation marks for strings in C are usually wrong, as C will calculate a number from the bytes of the string and use this as an int. There are only two occasions I know about where this would be correct and desired: If you want to have the ASCII value of a certain character (for example for setting a single character of a string, as well as a lot of string manipulation functions) or for four-byte constants that Carbon uses at some places. There are certainly other places, but in most cases, it is wrong.

If you want to be able to change your string, you have to create it as an array lik
Code:
char mystring[255];
or you can allocate memory dynamically.
Quote this message in a reply
DoG
Moderator
Posts: 869
Joined: 2003.01
Post: #6
ferum Wrote:ooh, so either way double quotation marks makes it unmodifiable? And single quotations for both is modifiable?
No. A string of char with a null terminator is enclosed by "…", while '…' is a single byte. For the string, you assign its location to your variable, for the char, you assign the value directly. So, the string may be read-only, while with the 'a', you immediately put it into writeable memory, unless you declare your variable const.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #7
Cochrane Wrote:If you want to be able to change your string, you have to create it as an array lik
Code:
char *mystring[255];

Unless you want an array of 255 string pointers, you probably won't want that star in there.
Quote this message in a reply
Member
Posts: 114
Joined: 2005.03
Post: #8
ThemsAllTook Wrote:Unless you want an array of 255 string pointers, you probably won't want that star in there.

Oh, sorry. I corrected it.
Quote this message in a reply
Member
Posts: 201
Joined: 2002.06
Post: #9
Oh, I see what is going on now. Okay, my answer is a bit more useless now.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #10
DoG Wrote:No. A string of char with a null terminator is enclosed by "…", while '…' is a single byte.
That's not completely true. You can have 4 letters placed within single quotes, which then becomes a "word" (or int). So you can' have something like 'word' or '/0cat', and put those into ints.

A string with double quotes may be placed in read-only memory, but it doesn't have to be. Also, you can return a string with double quotes from a function and it will live on. It's basically like a global variable, but under certain OSs, it's read-only. If you have an array, you can change whatever you want. So if you do
char cat[] = {'c', 'a', 't', '\0'};
you can then change it to "dog" if you want with regular array notation.
You can also do the following:
char cat[256];
strcpy(cat, "cat");
With the size of 256 in there, you can copy any string of length up to 255 in there no problem.

Hope that helps.
Quote this message in a reply
Member
Posts: 185
Joined: 2005.02
Post: #11
Blink Blush Huh

well, I'm not sure I followed any of that but I reread the section in my book (ok, more than once) and I think I understand it now.

If I initialize a string into an array,
Code:
char example[] = "this is a string";

Then it is stored in static memory (which is something I will learn about later on in the book, right now it is just something else to remember Smile )
the compiler see the name (example) as a synonym for the adress, therefore I cannot modify it (aka no using ++ to move to the next element). the name is effectively a constant. I can change the string being contained in the array, but I have to do it one element at a time.

If I initialize a string with a pointer pointing to it,
Code:
char *ExampleNumberTwo = "this is another string";

the string is put into static storage, and then the pointer variable ExampleNumberTwo is created and given the adress of the string. If I try to change the string using the pointer
Code:
ExampleNumberTwo[0] = 'T';

the compiler may accept it but under the current C standard there is no telling what will happen.

Am I right?
Quote this message in a reply
DoG
Moderator
Posts: 869
Joined: 2003.01
Post: #12
akb825 Wrote:That's not completely true. You can have 4 letters placed within single quotes, which then becomes a "word" (or int). So you can' have something like 'word' or '/0cat', and put those into ints.

That is a non-standard extension. Nevertheless, 'a' is still a byte, and while 'abcd' might yield a 32-bit int, it's still not a string. It doesn't become "abcd", it is not null terminated. That is a dangerous mistake there.

Apart from that:

char* string = "hello";

is nearly equivalent to

char string[] = "hello";

except that the former is incorrect, as it would have to be

const char* string = "hello";

because C string literals are read-only. You can muck your way around that, but you might crash.

char string[] = "…" creates a copy of the string in a static array you may modify

const char* string = "…" creates a pointer to a read-only string.
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #13
Just to be clear:
When you put a string in quotes in your code, that string is defined in a constants section of your executable. Open up your compiled executable and you can even find all your strings defined this way. Once loaded into memory (because this section of executable is fixed in length) tampering with its contents can overwrite executable code. This is why the compiler will give you errors and prevent you from assigning the string to a non-const.

With the array:
char string[] = ...

The compiler allocates the length of the constant string on the stack for that array. Then when the assignment takes place, the double quote string (found in the contants section) is copied into that stack memory array.

With the pointer:
char * string = ...

The assignment simply assigns the address of the string (in the constants) to the char pointer. This is bad, so you get the error.

For more insight into why there are strcpy() functions and all these kinds of restriction, read up on stack and heap memory. This will explain a lot of these nuances.



Further:
If you want to allocate a string of arbitrary length and change it, you must do a malloc. This allocates memory on the heap which you have full rights to mess with. You just have to remembr to clean it up.
Code:
char * string = (char*)malloc( sizeof(char) * 4); //4 chars in heap memory
string[0] = 'h';
string[1] = 'i';
string[2] = '\0';
//string contains "hi"

strcpy( string, "bye" );
//string now contains "bye"

//clean up
free(string);
string = NULL;

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
zKing
Unregistered
 
Post: #14
And to pick a nit:

'x' is a char, not a "byte".
C doesn't say much of anything about "bytes".

The only guarentees are:

sizeof(char) == 1 (this is NOT the number of bytes it is the number of chars, so this is basically doesn't mean much except when you see the next statement...)

sizeof(char) <= sizeof(short) <= sizeof(int) ... etc.

Again, sizeof is reporting the number of "chars" so everything is in units of a "char"

Also:
sizeof(char) is at least 8 bits
sizeof(short) is at least 16 bits
sizeof(int) is at least 16 bits
sizeof(long) is at least 32 bits

I worked on a 16 bit DSP where a char was 16 bits... and so was a short and so was an int. So in that case: sizeof(char) == sizeof(short) == sizeof(int) == 1.
Even more crazy is that I'm told that many 24 bit DSP's work the same way where a char/short/int == 24 bits.

Of course if you only deal with 32 bit desktop machines, this probably doesn't matter much.

EDIT:
Oh and modifying constant strings in the embedded world _WILL_ get you fired! Wink

char* foo = "hello world";
foo[2] = 'A';

... because often that string really is burned into ROM. On some other platforms, even tho it's loaded into RAM, the memory page is read only and you will cause an access fault. Just don't do it.
Quote this message in a reply
Moderator
Posts: 613
Joined: 2004.09
Post: #15
kelvin Wrote:
Code:
char * string = (char*)malloc( sizeof(char) * 4); //4 chars in heap memory
string[0] = 'h';
string[1] = 'i';
string[2] = '\0';
//string contains "hi"

strcpy( string, "bye" );
//string now contains "bye"

//clean up
free(string);
string = NULL;

Ok now you have me very confused,
char * string = (char*)malloc( sizeof(char) * 4);

returns an error of initializer element is not constant, can someone explain why that is please?

Kyle Richter
DragonForged.com
Twitter: @kylerichter
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Pascal language (pointer) problem sealfin 3 4,448 Nov 27, 2012 04:38 AM
Last Post: sealfin
  another c pointer question NelsonMandella 3 3,906 Mar 26, 2010 03:49 AM
Last Post: DoG
  efficient strings? fabien007 4 3,139 Dec 9, 2005 10:59 PM
Last Post: zKing
  Member function pointer LongJumper 6 4,919 Oct 31, 2005 05:53 PM
Last Post: LongJumper
  Cocoa Method to C Pointer KiroNeem 11 6,738 Sep 12, 2005 10:08 AM
Last Post: Zekaric