0 c
考虑以下简单的代码片段:
void SetCommand( const unsigned char *cmd )
{
iHeader[4] = *cmd;
}
...
const unsigned char *test = "\x72";
unsigned char iHeader[32];
hdrSetCommand(test);
Run Code Online (Sandbox Code Playgroud)
我想要做的是相当直接的:我有一个32个字符的数组,SetCommand应该将我的第4个字节设置为"\ x72".这里的代码工作正常,但我不明白为什么我必须写
iHeader[4] = *cmd /* instead of */ iHeader[4] = cmd ?
Run Code Online (Sandbox Code Playgroud)
而且,在宣布时
unsigned char *test = "\x72";
Run Code Online (Sandbox Code Playgroud)
我还得到一个错误消息,测试需要声明为常量?怎么会?
因为cmd是一个指针.它指向内存中的实际字符,它可能是一个奇怪的值,如0xbf001234.下图可以说明:
Memory address
+------------------+
0xef001214: | cmd (0xbf001234) |
(on stack) +------------------+
| +----+----+
0xbf001234: +---------------> |\x72|\x00|
(in read-only +----+----+
memory)
Run Code Online (Sandbox Code Playgroud)
当你取消引用 cmd(with *cmd)时,它实际上会在cmd指向的内存位置获取字符,这就是\x72你想要的.基本区别是:
"\x72"是一个指向常量char数组的指针{ '\x72', '\0' }.'\x72'是单个字符.你可能正在寻找的东西是:
#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);
Run Code Online (Sandbox Code Playgroud)
这会传递字符, '\x72'而不是指向包含该字符的字符串的指针.
还要注意明智地使用#defines - 这些通常会使代码更具可读性并且更不容易出错(例如,因为CMD_POS仅在一个点定义而不是分散在整个代码中作为幻数4).您应该仔细查看除零或一之外的所有幻数的使用.
至于你得到错误的原因是你的字符串变量需要定义为常量,这是因为你不能改变const char数组的内容(这是"\ x72"是一个双元素字符数组) -编译器可以自由地将它放入只读内存和/或共享它,如两个字符串:
const char *x = "Hello there";
const char *y = "there";
Run Code Online (Sandbox Code Playgroud)
被允许重叠如下:
Memory location
+---+---+---+---+---+---------+
0xbf005678 (x): | H | e | l | l | o | <space> |
+---+---+---+---+---+---------+
0xbf00567e (y): | t | h | e | r | e | \0 |
+---+---+---+---+---+---------+
Run Code Online (Sandbox Code Playgroud)
通过尝试将常量字符串视为非常量,您将破坏与编译器的契约.