简单的C char问题

时间:2009-07-29 12:26:46

标签: c

考虑以下简单的代码片段:

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"; 

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

5 个答案:

答案 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)

  1. 因为您传递的是指向字符串的指针,而不是单个字符。 *cmd取消引用数组中的第一个字符。

  2. 因为静态字符串位于只读数据段中。因此,任何指向它们的指针都应该是只读的。