我正在阅读《网络编程的Beej指南》,但在理解功能时遇到困难。该函数需要一个char *
指针,但会取消引用该指针并将其强制转换为(无符号long int)并执行一些按位操作。为什么我们不能仅仅将其作为
(unsigned int *)
,而不是(unsigned char *)
。同样,如果将参数替换为(void *)
,然后在内部代码中执行了类似的操作:
*(unsigned long int *)buf[0] << 24
我们会得到相同的结果吗? (很抱歉,这是我第一次在这里提出问题,所以请告知是否需要更多信息。)
unsigned long int unpacku32(unsigned char *buf)
{
return ((unsigned long int)buf[0]<<24) |
((unsigned long int)buf[1]<<16) |
((unsigned long int)buf[2]<< 8) |
buf[3];
}
答案 0 :(得分:2)
您所建议的内容并不能保证一定有效。除非buf
指向实际的unsigned long
,否则您将尝试将一种类型的对象读取为另一种类型的对象(除非您以unsigned char
读取)。如果您创建的指针值未正确对齐其类型,则可能会出现其他问题。
然后,还有字节序的问题。通过网络发送的字节通常以big-endian格式发送,即最高有效字节在前。如果您的系统是little-endian,它将以相反的顺序解释字节。
您发布的函数演示了以标准兼容方式从字节缓冲区反序列化unsigned long
的正确方法。
答案 1 :(得分:0)
这将使其依赖于平台的字节序。因此,我们从定义的顺序中挑选出零件以使其平台为中立。
答案 2 :(得分:0)
buf[0]
被视为8位无符号值。如果我们这样做:
(unsigned long int)buf[0] << 24
,通过强制转换,我们将其视为不是8位值,而是64位,因此我们有更多的空间可以使用。
我们仅转移了buf[0]
,buf[1]
,并且在转移过程中未考虑其他字段。
如果您想转换为unsigned long
,可以说一个字符串"aabbccd"
,而我们并不关心字节顺序,可以按照以下方式进行操作:
char* str = const_cast<char *>("aabbccd\0");
unsigned long value = *(reinterpret_cast<unsigned long *>(str));
std::cout << value << std::endl;
std::cout << reinterpret_cast<char *>(&value) << std::endl;
应该指出,unsigned long
最多只能存储8个字符,因为它是64位整数。
但是,如果许多平台都将使用相同的数据,则由于字节顺序的原因,仅这样做是不够的。有人提到您的书中提到的方法是平台无关的。
答案 3 :(得分:0)
该函数需要一个
char *
指针,但会取消引用 指针并将其强制转换为(unsigned long int
)并执行一些 按位运算。
实际上,代码的作用是使用数组索引运算符从缓冲区中提取第一个字节,将其强制转换为unsigned long int
,然后然后执行一些按位运算。被取消引用的指针是unsigned char *
与长整数无关。
为什么我们不能仅将其传递为(unsigned int *)而不是 (无符号字符*)。
因为它不是指向任何类型的整数的指针。它是指向unsigned char
缓冲区(即字节)的指针。将指针视为指向其他类型的指针可能会导致违反“严格别名规则”(我鼓励您阅读)。
如果参数被(void *)代替,然后在内部代码中 做过类似
*(unsigned long int *)buf[0] << 24
的事情 结果相同吗?
不。如果将buf
定义为void*
,则buf[0]
是无意义的表达式。如果将buf
定义为unsigned long int *
或强制转换为buf[0]
,则unsigned long int
是unsigned char
,而不是算法期望的function account(fname, lname){
this.checking = 0;
this.savings = 0;
this.total = this.checking + this.savings;
this.openDate = new Date();
this.transactions = [];
this.firstName = fname;
this.lastName = lname;
this.deposit = (account, amount) => {
this[account] += amount;
};
this.withdrawal = (account, amount) => {
this[account] -= amount;
}
}
var client = new account("Name", "Name");
client.deposit('checking', 5000);
console.log(client);
。几乎肯定会设置太多位(最多64位,而不是8位),并且表达式的结果将无效。