Skip to main content
GameDev.net gamedev.net
🔒 Locked

Odd strcpy problem

Started by Crypter Nov 30, 2008 at 4:55 PM 10 replies 1.9k views
Original Post
Crypter
Crypter
Hey everyone, Im having some trouble with a piece of code. Basically I am trying to use strcpy() to set a single entry in an array of strings. However, instead of setting one entry, it seems to set all entries to the same string. :/ Here is where the array is created. The software runs in an environment without dynamic allocation, so its created statically:
//! array of strings (max ENTRY_LENGTH characters per string)
static char _entries[MAX_ENTRIES][ENTRY_LENGTH];
m_bootEntries = (char**) _entries;

//! this option is always the first one
m_bootEntries[0] = "Enter Command Parser";
The first entry (shown above) is set correctly and works fine. The problem comes when I use strcpy() to copy a string into m_bootEntries. If I use strcpy(), it sets all corresponding entries to the same string rather then the one. :/
//! sets entries 1 to 'n' to this string??
strcpy (m_bootEntries[1], "entry string");
Does anyone know where I might of gone wrong? Thanks for any suggestions[smile]
rip-off
rip-off
Your cast is suspicious. Surely if such a conversion was legal the compiler wouldn't require a cast?
Crypter
Crypter
Quote:
Your cast is suspicious. Surely if such a conversion was legal the compiler wouldn't require a cast?

m_bootEntries is declared as a char**. Without the cast I get the following on that line of code:
error C2440: '=' : cannot convert from 'char [20][40]' to 'char **'
Are these not the same basic types? Or am I mistaken? (Probably...I did not like the cast either).
DevFred
DevFred
Quote:
Original post by Crypter
cannot convert from 'char [20][40]' to 'char **'
Are these not the same basic types?

No. A two-dimensional array is very different from an array of pointers.
rip-off
rip-off
No, arrays and pointers are not the same (looking for a good link).

This code seems to work, but its a bit ugly:
typedef char EntryList[MAX_ENTRIES][ENTRY_LENGTH];static EntryList _entries;void foo(){	for(int i = 0 ; i < MAX_ENTRIES; ++i)	{		_entries[0] = '\0';	}	EntryList *m_bootEntries = &_entries;	strcpy((*m_bootEntries)[0],"Enter Command Parser");	strcpy ((*m_bootEntries)[1], "entry string");}
DevFred
DevFred
Why so complicated?
static char _entries[20][40];strcpy(_entries[0], "Enter Command Parser");strcpy(_entries[1], "entry string");
rip-off
rip-off
With the m_ prefix, I assumed he wanted to reference the array indirectly, as a member of some structure. If you have direct access to the entries table, then yes of course that would be easier.
DevFred
DevFred
Alright then, pointers to arrays to the rescue:

#define MAX_ENTRIES 20#define ENTRY_LENGTH 40static char _entries[MAX_ENTRIES][ENTRY_LENGTH];char (*m_bootEntries)[ENTRY_LENGTH] = _entries;// the 2D array decays into a pointer to an array of 40 charactersstrcpy(m_bootEntries[0], "Enter Command Parser");strcpy(m_bootEntries[1], "entry string");
rip-off
rip-off
I was trying to get something similar to compile... but I must have left something out, it wouldn't compile. Either that or I mismatched the array sizes or something equally stupid [embarrass].
Crypter
Crypter
Quote:
With the m_ prefix, I assumed he wanted to reference the array indirectly, as a member of some structure. If you have direct access to the entries table, then yes of course that would be easier.

That was indeed my intention. I wanted to indirectly refrence the array through a member pointer to try keeping the size of the overall class down. I modified my code to work similarly to what you have posted and it worked!

DevFred's solution seems like it should work as well. Im going to try DevFred's solution as well as it seems easier to work with.

Thanks for the help! [smile]
DevFred
DevFred
Quote:
Original post by Crypter
Here is where the array is created. The software runs in an environment without dynamic allocation, so its created statically:

static char _entries[MAX_ENTRIES][ENTRY_LENGTH];
m_bootEntries = (char**) _entries;

I am surprised that the first strcpy seemed to work. The only explanation I can come up with is that _entries is placed at address 0 in your "environment" (some embedded device?). That means the addresses 0 through 799 are reserved for your characters, and initially, they are set to 0.

Now, when you say m_bootEntries = (char**) _entries, the _entries array implicitly decays into a pointer to its first element (and the first element is of type char[40]) before the cast, but then you say "No, this isn't a pointer to a char[40], it is actually a pointer to a pointer to a single character".

The decayed value is the address of _entries which I presumed was 0. So in effect with your cast you say "0 is a memory location where you find a pointer to a char", and what value is currently stored at 0? The same value 0, because we haven't stored anything in there yet. But after we copied the string into that location, m_bootEntries now points to something entirely different, it points to the address "Ente" (assuming a 32 bit environment), whatever that means. Have you tried printing m_bootEntries[0], or did you just look at the memory and saw the string at address 0?

Learn the differences between arrays and pointers, it's important when you program in C.
Crypter
Crypter
Quote:
Have you tried printing m_bootEntries[0], or did you just look at the memory and saw the string at address 0?

Neither. I put a loop to display each entry in the boot entry array. Each entry matched with the same string that I was trying to print. Each entry was the same string after a single strcpy call.

I can see where the problem is at though. Thanks for the great explanation [smile] Im going to read the link you posted.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.