简单的C char问题

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)

我还得到一个错误消息,测试需要声明为常量?怎么会?

pax*_*blo 6

因为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)

通过尝试将常量字符串视为非常量,您将破坏与编译器的契约.