哪个更具可读性(C ++ =)

时间:2009-05-31 04:51:43

标签: c++ c

int valueToWrite = 0xFFFFFFFF;
static char buffer2[256];
int* writePosition = (int* ) &buffer2[5];
*writePosition = valueToWrite;

//OR
* ((int*) &buffer2[10] ) = valueToWrite;

现在,我问你们哪一个你觉得更具可读性。涉及临时变量或一步技术的两步技术?

不要担心优化,他们都优化到相同的东西,你可以在这里看到。 告诉我哪一个对你来说更具可读性。

or  DWORD PTR ?buffer2@?1??main@@9@4PADA+5, -1
or  DWORD PTR ?buffer2@?1??main@@9@4PADA+10, -1

10 个答案:

答案 0 :(得分:19)

int* writePosition = (int* ) &buffer2[5]

或者

*((int*) &buffer2[10] ) = valueToWrite;

两者都不正确,因为在某些平台上访问未对齐的值(+5 +10)可能会花费数百个CPU周期,而在某些平台上(如旧版ARM)则会导致非法操作。

正确的方法是:

memcpy( buffer+5, &valueToWrite, sizeof(valueToWrite));

它更具可读性。

答案 1 :(得分:9)

将它封装在一个类中后,使用哪种技术并不重要。方法名称将提供有关代码正在执行的操作的说明。因此,在大多数情况下,您不必深入研究实际的impl。看看发生了什么。

class Buffer
{
    char buffer2[256];
public:
    void write(int pos, int value) { 
       int* writePosition = (int*) &buffer2[pos];
       *writePosition = value;
    }
}

答案 2 :(得分:4)

如果我被迫选择,我会说1.但是,我会注意到所呈现的代码非常像C;我会回避任何一个并重新审视这个问题。这是一个更简单的C ++ - y

const char * begin = static_cast<char*>(static_cast<void*>(&valueToWrite));
std::copy(begin, begin+sizeof(int), &buffer2[5]);

答案 3 :(得分:2)

第一个例子更具可读性,纯粹基于你的大脑不必破解指针操作。

这将减少开发人员第一次查看代码需要了解实际情况的时间。根据我的经验,这与降低引入新bug的可能性密切相关。

答案 4 :(得分:1)

我发现第二个更短的一个更容易阅读。

然而,我怀疑这取决于你是否是那种能够轻易“获得”指针的人。

但是从char *到int *的类型转换有点尴尬。我认为有一个很好的理由需要这样做。

答案 5 :(得分:1)

注意 - 由于对齐问题,此代码可能无效!为什么不使用memset

#include <string.h>
memset(buffer2+10, 0xFF, 4);

答案 6 :(得分:1)

如果您能够将自己绑定到单个编译器(或者预处理器可以解决兼容性问题),则可以使用packed-structs选项为您正在编写的值获取符号名称。例如,在GCC上:

struct __attribute__ ((__packed__)) packed_struct
{
  char stuff_before[5]
  int some_value;
}

/* .... */

static char buffer2[256];
struct packed_struct *ps = buffer2;
ps->some_value = valueToWrite;

这有许多优点:

  • 如果您为自己的字段命名,您的代码会更清楚地反映您正在做的事情。
  • 由于编译器知道您所使用的平台是否支持高效的非对齐访问,因此它可以自动选择本机未对齐访问,或者在不支持未对齐访问的平台上进行适当的解决方法。

但是,再次,主要的缺点是没有任何标准化的语法。

答案 7 :(得分:0)

最具可读性的是变体,并添加了关于你在那里做什么的评论。

话虽如此,我鄙视引入的变量只是为了一次性使用几行。在维护区域完成我的大部分工作,在我的脸上榨取了几十个变量名称,而不必编写解释性注释,这让我处于优势地位。

答案 8 :(得分:0)

肯定:

* ((int*) &buffer2[10] ) = valueToWrite;

我解析它不是一步而是几步,这就是为什么它更具可读性:我将所有步骤都放在一行中。

答案 9 :(得分:0)

从可读性的角度来看,代码的行为应清晰明了,但是“清晰”并不是我描述这两种选择的方式。实际上,它们与“清除”相反,因为它们是不可携带

除了对齐问题外,还有整数表示(大小因系统而异,符号表示,字节序和填充要放入汤中也是如此)。因此,代码在系统之间的行为是不稳定

如果要清楚知道算法应该做什么,则应该明确地将每个字节放入正确的位置。例如:

void serialise_uint_lsb(unsigned char *destination, unsigned source) {
    destination[0] = source & 0xff; source >>= 8;
    destination[1] = source & 0xff; source >>= 8;
    assert(source == 0);
}

void deserialise_uint_lsb(unsigned *destination, unsigned char *source) {
    *destination = 0;
    *destination <<= 8; *destination += source[1];
    *destination <<= 8; *destination += source[0];
}

序列化和反序列化是程序员的惯用概念... *printf*scanf是序列化/反序列化的形式,例如,除了被惯用地灌输到您的脑海中,小数点后一位) ...这是您代码的问题;您的代码不会告诉系统整数的方向,有多少字节等等,这是个坏消息。

使用序列化/反序列化功能。程序员会对此最了解。