Because cmd
is a pointer. It points to the actual characters in memory and it's likely to be a weird value like 0xbf001234
. The following diagram may illustrate:
Memory address
+------------------+
0xef001214: | cmd (0xbf001234) |
(on stack) +------------------+
| +----+----+
0xbf001234: +---------------> |\x72|\x00|
(in read-only +----+----+
memory)
When you de-reference cmd
(with *cmd
), it actually gets the character at the memory location where cmd
points to, which is the \x72
that you want. The basic difference is:
"\x72"
is a pointer to a constant char array { '\x72', '\0' }
.
'\x72'
is the single character.
What you were probably looking for was something along the lines of:
#define CMD_POS 4
#define CMD_TEST '\x72'
...
unsigned char iHeader[32];
void hdrSetCommand (unsigned char cmd) {
iHeader[CMD_POS] = cmd;
}
...
unsigned char test = CMD_TEST;
hdrSetCommand (test);
This passes the character '\x72'
rather than a pointer to the string containing that character.
Also note the judicious use of #define
s - these usually make the code a lot more readable and less prone to errors (since, for example, CMD_POS is only defined at one point rather than scattered throughout the code as the magic number 4). You should look carefully at the use of all magic numbers other than zero or one.
As to the reason why you got the error stating that your string variable needs to be defined constant, this is because you cannot change the contents of a const char
array (which is what "\x72" is, a two-element character array) - the compiler is free to place it into read-only memory and/or share it such as the two strings:
const char *x = "Hello there";
const char *y = "there";
being allowed to overlap as follows:
Memory location
+---+---+---+---+---+---------+
0xbf005678 (x): | H | e | l | l | o | <space> |
+---+---+---+---+---+---------+
0xbf00567e (y): | t | h | e | r | e | \0 |
+---+---+---+---+---+---------+
By attempting to treat a constant string as non-constant, you break your contract with the compiler.