了解类型转换(指针)

时间:2019-02-17 20:06:45

标签: c++ c

我正在阅读《网络编程的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];
}

4 个答案:

答案 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 intunsigned 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位),并且表达式的结果将无效。