【问题标题】:Is it necessary to cast individual indices of a pointer after you cast the whole pointer in c? Why? [closed]在 c 中转换整个指针后是否有必要转换指针的单个索引?为什么? [关闭]
【发布时间】:2021-11-24 19:28:53
【问题描述】:

在下面的代码中,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[i] 对于任何有效索引 i 已经具有 uint8_t 类型。不需要单独的元素演员表。
  • 如果这是 C++,那么这段代码中不应该有任何 c 风格的转换。请不要混淆 C 和 C++,它们是两种不同的语言。只标记两者的问题是关于两者的互操作
  • 显示的代码通过 1) 将 IP 地址转换为 uint32_t,2) 将 uint32_t 地址拆分为四个 uint8_t 值,以及 3) 使用它们创建相同的值来完成什么uint32_t 开始时的值,在第 1 步?那应该完成什么?你的inet_addr 真的接受 NULL 指针作为有效的输入参数吗?
  • 顺便提一下,inet_addrinet_pton 取代。
  • 作者可能应该检查inet_addr 的返回值是否有错误,并用uint8_t 数组替换所有乱七八糟的东西,并调用ntohl()

标签: c++ c pointers casting


【解决方案1】:

取消引用ptr 的任何索引(即ptr[0]ptr[1] 等)将具有uint8_t 类型。对它们进行的铸造是多余的。

【讨论】:

    【解决方案2】:

    程序员为什么要这么做?

    无知、恐惧或其他无能。

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

    如果我们删除所有在初始演员表之后的演员表会有什么不同吗?

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

    此代码将 IPv4 IP 地址转换为 IP 号码。

    不,它没有,不正确;密码坏了。

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

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

    【讨论】:

    • 猜测原来的程序员知道代码被破坏了,并且他或她认为演员足以修复它(转换提升的@ 987654339@ 值返回到uint8_t)。
    【解决方案3】:

    我怀疑那是 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;
    }
    

    【讨论】:

    猜你喜欢
    • 2019-02-03
    • 2010-09-11
    • 2020-12-10
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-24
    • 2013-06-03
    相关资源
    最近更新 更多