• We’re currently investigating an issue related to the forum theme and styling that is impacting page layout and visual formatting. The problem has been identified, and we are actively working on a resolution. There is no impact to user data or functionality, this is strictly a front-end display issue. We’ll post an update once the fix has been deployed. Thanks for your patience while we get this sorted.

old-school C strings

professor1942

Senior member
Alright, my crappy textbook is trying to tell me that this:

char sentence[] = "I like to eat pork chops";

is the same thing as this:

char *sentence = "I like to eat pork chops";

yet if I try manipulating the second version with strtok, strcpy etc. I get a runtime error. Can someone explain to me what the difference is?

Thanks
 
Originally posted by: professor1942
Alright, my crappy textbook is trying to tell me that this:

char sentence[] = "I like to eat pork chops";

is the same thing as this:

char *sentence = "I like to eat pork chops";

yet if I try manipulating the second version with strtok, strcpy etc. I get a runtime error. Can someone explain to me what the difference is?

Thanks

make sure when you pass it you use * then char name and it should work.
If I ever use char arrays I use the first method.
Most of the time I use STL String class.
 
I'm actually using <cstring> in VS C++ 2005.

The problem is that these old string-handling library functions (strtok, strcpy etc.) require a pointer argument, so dereferencing it in the call results in a compile error: cannot convert parameter 1 from 'char' to 'const char *'.
 
Works for me...

As for the first declaration of sentence, it's also a pointer (to the first element in the char array (string)). The constructor for char automatically adds a NULL terminator (\0) to the end of the string when you initialize it. When you call strcpy on the array, you are actually giving strcpy the pointer to the first element in the array. strcpy takes it from there until it hits the terminator (NULL). target is declared as 25 elements because the sentence is 24 characters long and plus, in order to accomodate the NULL terminator, one character.
 
Originally posted by: professor1942
I'm actually using <cstring> in VS C++ 2005.

The problem is that these old string-handling library functions (strtok, strcpy etc.) require a pointer argument, so dereferencing it in the call results in a compile error: cannot convert parameter 1 from 'char' to 'const char *'.
I think you'd better post your precise code. I suspect a misunderstanding about the nature of arrays. You do understand that an array is a pointer, right?
 
Originally posted by: professor1942
Alright, my crappy textbook is trying to tell me that this:

char sentence[] = "I like to eat pork chops";

is the same thing as this:

char *sentence = "I like to eat pork chops";

yet if I try manipulating the second version with strtok, strcpy etc. I get a runtime error. Can someone explain to me what the difference is?

Thanks

Big difference actually.

The first statement creates a large enough character array, and puts "I like..." into it.
The second state creates a character pointer, and make it point to a constant string "I like to...".

Depending on your environment, the memory pointed to by the second pointer can be marked as read-only, and any attempt to change it will cause errors.
 
Originally posted by: professor1942
I'm actually using <cstring> in VS C++ 2005.

The problem is that these old string-handling library functions (strtok, strcpy etc.) require a pointer argument, so dereferencing it in the call results in a compile error: cannot convert parameter 1 from 'char' to 'const char *'.

You need to call CString::AllocSysString() to extract a tchar* out of the CString. AllocSysString returns a pointer referencing the pre-allocated string in it for you. So, it would go something like:

strcpy(target, myCString.AllocSysString());

But I believe strcpy must be aliased to _tcscpy() and target must be a unicode string (TCHAR*/BSTR). I think the former will automatically happen if you include <tchar.h>.
 
Originally posted by: kamper

I think you'd better post your precise code. I suspect a misunderstanding about the nature of arrays. You do understand that an array is a pointer, right?

Yes, that's why this thing has me puzzled:


char sentence[] = "I like to eat pork chops";
char *sentence2 = "I like to eat pork chops";

char *tokenPtr;
tokenPtr = strtok( sentence, " " ); // works fine

tokenPtr = strtok( sentence2, " " ); // crashes


Anyway, thanks for the replies so far - I'll study them a bit more.




 
Originally posted by: professor1942
Originally posted by: kamper

I think you'd better post your precise code. I suspect a misunderstanding about the nature of arrays. You do understand that an array is a pointer, right?

Yes, that's why this thing has me puzzled:


char sentence[] = "I like to eat pork chops";
char *sentence2 = "I like to eat pork chops";

char *tokenPtr;
tokenPtr = strtok( sentence, " " ); // works fine

tokenPtr = strtok( sentence2, " " ); // crashes


Anyway, thanks for the replies so far - I'll study them a bit more.

this is exactlywhat I was talking about, strtok modifies the string that is passed in. sentence2 points to a string literal which is supposed to be read-only.

 
Originally posted by: dighn
this is exactlywhat I was talking about, strtok modifies the string that is passed in. sentence2 points to a string literal which is supposed to be read-only.

dighn is right. I just tried the following code and it crashes when I try to assign a new value.
 
Originally posted by: professor1942
OK I understand now, both can be used to store a string but only the array version can be modified.

If you use malloc to allocate the memory, you can modify it.


 
Originally posted by: professor1942
Originally posted by: kamper

I think you'd better post your precise code. I suspect a misunderstanding about the nature of arrays. You do understand that an array is a pointer, right?
Yes, that's why this thing has me puzzled:

char sentence[] = "I like to eat pork chops";
char *sentence2 = "I like to eat pork chops";

char *tokenPtr;
tokenPtr = strtok( sentence, " " ); // works fine

tokenPtr = strtok( sentence2, " " ); // crashes

Anyway, thanks for the replies so far - I'll study them a bit more.
My bad, it sounded like you actually were referencing the variables differently. I just learned about statically declared char*s being read-only too 🙂
Originally posted by: dighn
Depending on your environment, the memory pointed to by the second pointer can be marked as read-only, and any attempt to change it will cause errors.
What are the environmental factors? Is it part of the spec that the compiler can decide or is it different spec versions?
 
Originally posted by: kamper
Originally posted by: dighn
Depending on your environment, the memory pointed to by the second pointer can be marked as read-only, and any attempt to change it will cause errors.
What are the environmental factors? Is it part of the spec that the compiler can decide or is it different spec versions?

I don't know the details. It's probably one of those implementation specific/undefined rules that depends on your compiler/OS. In any case it's safest to just assume that literals are read-only.
 
Originally posted by: xtknight
They aren't read-only...? You just can't use strcpy for some reason.

you can assign to the pointer no problem, but you can't modify the memory referred by the pointer. when you use [], it actually creates some writeable memory (probably on the stack) that is initialized with the string, but when you use *, the compiler just makes the pointer point to some constant string in memory that's probably part of the original executable image.
 
Originally posted by: dighn
I don't know the details. It's probably one of those implementation specific/undefined rules that depends on your compiler/OS. In any case it's safest to just assume that literals are read-only.
Definitely.

If you do something like

char greeting[] = "Hello " ;
char* name = "Bob" ;

A compiler might let you do

strcat( greeting, name )

but at runtime you are trashing some part of memory since even if it's on the stack, the heap, or in a writable data segment it is only exactly the right size for "Hello" + \0 and will not magically grow to hold the additional characters.

You need to call CString::AllocSysString() to extract a tchar* out of the CString. AllocSysString returns a pointer referencing the pre-allocated string in it for you.
Not if you just need const char* access, CString has an LPCTSTR operator.
 
Originally posted by: DaveSimmons
but at runtime you are trashing some part of memory since even if it's on the stack, the heap, or in a writable data segment it is only exactly the right size for "Hello" + \0 and will not magically grow to hold the additional characters.
(v)asprintf ftw!! Too bad they're not really standard 🙁 Very handy when suffering from c string handling madness.

Btw, I like pork chops too 😀
 
What's the difference between the heap and stack? How does one denote that a variable should be on the heap, or on the stack and what difference does it make? Is one always read-only? (And what are they in general??)

char *string = "I like to eat pork chops."; // this is a constant?
char string[] = "I like to eat pork chops."; // yet this is modifiable?
 
The stack is function-specific memory. It stores function parameters and return values, stack data and other such things. It grows with every function call and shrinks with every function return. Anything that you declare local to a function gets placed on the stack (and that's why you can't pass pointers to local variables as returns, because once a function returns, it's memory on the stack is invalid).

The heap is kept at the opposite end of memory and is just a big blob that you make allocations out of. Any call to malloc and friends gives you heap memory. The char * declaration goes somewhere else altogether, I'm guessing, in a section where lots of read-only data goes.
 
Plus the stack is often small (as little as 1 MB), while the heap is massive (almost all of the unused address space of your process, up to 2 GB).

placing large structures, class objects or arrays on the stack can quickly lead to stack overflow (out of space) especially if you nest function calls and each uses stack space.
 
Originally posted by: DaveSimmons
Plus the stack is often small (as little as 1 MB), while the heap is massive (almost all of the unused address space of your process, up to 2 GB).

placing large structures, class objects or arrays on the stack can quickly lead to stack overflow (out of space) especially if you nest function calls and each uses stack space.
Shouldn't the stack be allowed to grow as long as there is space? Like if the heap is relatively small and defragmented, it should be able to take up most of the address space.
 
Originally posted by: kamper
Shouldn't the stack be allowed to grow as long as there is space? Like if the heap is relatively small and defragmented, it should be able to take up most of the address space.
It doesn't work that way, the stack is given a fixed block of memory at process startup that can't be moved or grown. You also set a fixed size when creating threads.

It's an assembly-level, CPU-hardware-supported allocation for the process that's independent of whatever mix of language(s) you are using, though you can set a desired (fixed) size for the process using linker flags.
 
Back
Top