考虑以下简单的代码片段:
void SetCommand( const unsigned char *cmd )
{
iHeader[4] = *cmd;
}
...
const unsigned char *test = "\x72";
unsigned char iHeader[32];
hdrSetCommand(test);
我想做的事情非常简单:我有一个32个字符的数组,而SetCommand应该将第4个字节设置为“\ x72”。这里的代码工作正常,但我不明白为什么我必须写
iHeader[4] = *cmd /* instead of */ iHeader[4] = cmd ?
此外,在宣布
时unsigned char *test = "\x72";
我还得到一条错误消息,测试需要声明为常量?怎么样?
答案 0 :(得分:6)
因为cmd
是指针。它指向内存中的实际字符,它可能是一个奇怪的值,如0xbf001234
。下图可以说明:
Memory address
+------------------+
0xef001214: | cmd (0xbf001234) |
(on stack) +------------------+
| +----+----+
0xbf001234: +---------------> |\x72|\x00|
(in read-only +----+----+
memory)
当您取消引用 cmd
(*cmd
)时,它实际上会在cmd
指向的内存位置获取该字符,这是你想要的\x72
。基本区别是:
"\x72"
是指向常量字符数组{ '\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);
这会传递字符 '\x72'
,而不是指向包含该字符的字符串的指针。
还要注意#define
s的明智使用 - 这些通常会使代码更具可读性并且更不容易出错(例如,因为CMD_POS仅在一个点定义而不是分散在整个代码中神奇的数字4)。您应该仔细查看除零或一个以外的所有幻数的使用。
至于你得到错误的原因,说明你的字符串变量需要定义为常量,这是因为你不能改变const char
数组的内容(这是“\ x72”是什么,一个双元素字符数组) - 编译器可以自由地将它放入只读存储器和/或共享它,例如两个字符串:
const char *x = "Hello there";
const char *y = "there";
允许重叠如下:
Memory location
+---+---+---+---+---+---------+
0xbf005678 (x): | H | e | l | l | o | <space> |
+---+---+---+---+---+---------+
0xbf00567e (y): | t | h | e | r | e | \0 |
+---+---+---+---+---+---------+
通过尝试将常量字符串视为非常量,您将破坏与编译器的契约。
答案 1 :(得分:4)
您需要*cmd
,因为要检索char
值,您需要取消引用char*
指针,并且需要使用*运算符。
您需要将test
声明为const
因为它指向一个常量字符串文字 - 将常量字面值的地址指定给指向非const的指针(char *,而不是const char) *)违反const-correctness并被禁止,
答案 2 :(得分:2)
应该是:
void SetCommand( unsigned char cmd ) {
iHeader[4] = cmd;
}
const unsigned char test = '\x72';
unsigned char iHeader[32];
你试图将一个点分配给一个字节,这将无效。
答案 3 :(得分:1)
“\ x72”是一个字符串,因此你需要一个指向该字符串中所有字符的指针,所以在
之后const unsigned char *test = "\x72";
测试指向两个字符'\ x72'和空终结符'\ x0'
的第一个字符您可以将其重写为
const unsigned char test = '\x72';
test现在是一个字符,然后您可以将您的函数编写为
void SetCommand( const unsigned char cmd )
{
iHeader[4] = cmd;
}
您不再需要* cmd,因为cmd不是指针,因此您无需取消引用它以获取其值
希望这有帮助。
答案 4 :(得分:0)
因为您传递的是指向字符串的指针,而不是单个字符。 *cmd
取消引用数组中的第一个字符。
因为静态字符串位于只读数据段中。因此,任何指向它们的指针都应该是只读的。