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
答案 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
是序列化/反序列化的形式,例如,除了被惯用地灌输到您的脑海中,小数点后一位) ...这是您代码的问题;您的代码不会告诉系统整数的方向,有多少字节等等,这是个坏消息。
使用序列化/反序列化功能。程序员会对此最了解。