良好形式:指针与局部变量与阵列索引

时间:2010-02-23 20:48:25

标签: c

请原谅我,如果这是一个微不足道的问题 - 我通常是一个控制系统人(plc和自动化),但最近我发现自己参与了一些嵌入式微控制器和PC项目。

假设我有一个接受指向“命令字节”数组的指针的函数,通常长度为5或10个字节,如下所示:

char cmd_i2c_read(unsigned char *cmd, unsigned short cmd_len) { ... }

我想解码命令字节(* cmd)。

是否有更好的形式:

  1. 创建指示每个字节用途的局部变量:

    unsigned char device_address = cmd[2];
    unsigned char register_address = cmd[3];
    unsigned char num_bytes = cmd[4];
    // use the local variables: if(num_bytes &le 0xFF) { do_stuff(device_address, register_address, num_bytes); }
  2. 创建本地指针:

    unsigned char *device_address = &cmd[2];
    unsigned char *register_address = &cmd[3];
    unsigned char *num_bytes = &cmd[4];
    // use the pointers: if(*num_bytes &le 0xFF) { do_stuff(*device_address, *register_address, *num_bytes); }
  3. 直接索引* cmd数组:
    if(cmd[4] <= 0xFF) { do_stuff(cmd[2], cmd[3], cmd[4]); }

7 个答案:

答案 0 :(得分:4)

选项1很清楚,但有点罗嗦。我根本不喜欢2,3很难理解。就个人而言,我更喜欢使用结构来做这种事情。

typedef struct  {
   unsigned char whatever[2];
   unsigned char device_address;
   unsigned char register_address;
   unsigned char num_bytes;
   }  CMD;

CMD * pcmd = (CMD *)&cmd[0];

// use the local variables:
if(num_bytes ≤ 0xFF) {
    do_stuff(pcmd->device_address, pcmd->register_address, pcmd->num_bytes);

答案 1 :(得分:3)

我更喜欢第3项,但归结为偏好。

答案 2 :(得分:3)

恕我直言,第一种方式更好。它比3号更容易阅读,因为你不需要知道函数的签名来理解参数是什么。

对于更大的数据结构,我会使用数字2,即使用指针,这样您就不必复制值。但在这种情况下,差异并不显着,我认为* /&amp;略微降低可读性。

答案 3 :(得分:2)

绝对是#1。它使代码的其余部分更具可读性,并且使用正常变量所做的指针会无缘无故地使问题复杂化。编译器将优化您从#3获得的任何微观性能增益。

答案 4 :(得分:1)

如果是我,我会将其写为#3,但使用数组索引的符号名称来提高可读性: -

#define DEVICE_ADDRESS 2
#define REGISTER_ADDRESS 3
#define NUM_BYTES 4

if (cmd[NUM_BYTES] <= 0xFF) {
    do_stuff(cmd[DEVICE_ADDRESS], cmd[REGISTER_ADDRESS], cmd[NUM_BYTES]);
}

你当然可以用const int,enums等替换宏。我喜欢这个选项的原因是其他两个选项需要使用额外的局部变量。编译器可能会也可能不会优化它们,具体取决于它的实现和您选择的优化级别,但它们对我来说似乎是一种不必要的额外间接。

答案 5 :(得分:0)

我最喜欢1,它比其他人更可读。

如果性能是一个重要问题(我的意思很重要,比如“我们需要每增加0.01%的速度,我们就可以获得”),你将不得不进行基准测试,因为它真的取决于编译器哪个序列最终将以最快的代码结束( 1可能有不必要的副本,2可能包含由于指针别名限制的超级负载,3如果寄存器分配器真的搞砸可能会导致超级负载)

答案 6 :(得分:0)

对我来说,这取决于你对缓冲区做什么,

尽管所有事情都是平等的,但我可能更喜欢让缓冲区成为一个结构(假设对齐警告),如果不这样做,则直接索引缓冲区,尽管没有魔术数字。