在 c 中转换整个指针后,是否有必要转换指针的各个索引?为什么?

Is it necessary to cast individual indices of a pointer after you cast the whole pointer in c? Why?

在下面的代码中,ip 地址被转换为 uint8_t *。 但是下面再次将转换指针的每个索引转换为 uint8_t。 程序员为什么要这样做?如果我们删除所有那些在初始演员表之后出现的演员表,会有什么不同吗?此代码将 IPv4 IP 地址转换为 IP 编号。谢谢

uint32_t Dot2LongIP(char* ipstring)
{
    uint32_t ip = inet_addr(ipstring);
    uint8_t *ptr = (uint8_t *) &ip;
    uint32_t a = 0;

    if (ipstring != NULL) {
        a =  (uint8_t)(ptr[3]);
        a += (uint8_t)(ptr[2]) * 256;
        a += (uint8_t)(ptr[1]) * 256 * 256;
        a += (uint8_t)(ptr[0]) * 256 * 256 * 256;
    }
    return a;
}

取消引用 ptr 的任何索引(即 ptr[0]ptr[1] 等)的类型将是 uint8_t。对它们执行的转换是多余的。

Why the programmer has done this?

无知、恐惧或其他无能。

ptr的类型是uint8_t *,所以ptr[i]的类型是uint8_t。将 uint8_t 转换为 uint8_t 没有任何效果。另外,放在括号里是没有效果的。

Does it make a difference if we remove all those casts that come after the initial cast?

是的,它使代码更小更清晰。它对程序语义没有影响。

This code converts an IPv4 IP Address to an IP Number.

不,不是,不正确;代码已损坏。

uint8_t 值用于乘以 256 时,将应用通常的算术转换。这些将 uint8_t 提升为 int,然后 * 运算符的结果是 int。对于 ptr[0],由于执行了两次 256 的乘法运算,结果仍然是 int。不幸的是,如果设置了 ptr[0] 的高位(第 7 位),这些乘法会溢出 32 位 int。那么程序的行为不是C标准定义的。

为避免这种情况,值应转换为 uint32_t。 (这只是为了让算术正确;我没有断言拆开 inet_addr 返回的 in_addr_t 并以这种方式重新组合它的有用性。)

我怀疑那是Arduino代码:)

uint32_t Dot2LongIP(char* ipstring)
{
    uint32_t ip = inet_addr(ipstring);
    
    return return nothl(ip);
}

或者如果您不想使用 htonl

uint32_t Dot2LongIP(char* ipstring)
{
    uint32_t ip = inet_addr(ipstring);
    
    ip = ((ip & 0xff000000) >> 24) | ((ip & 0x00ff0000) >> 8) | 
         ((ip & 0x0000ff00) << 8)  | ((ip & 0x000000ff) << 24);

    return ip;
}