【问题标题】:need to store a string values into a int instead of a 4 byte sized char array需要将字符串值存储到 int 而不是 4 字节大小的 char 数组中
【发布时间】:2014-02-13 02:20:18
【问题描述】:

我将 ip 地址 值存储到大小为 4 字节的 char 数组(uint8_t) 中,而不是我需要将该值存储到 单个整数,怎么做

    uint8_t ip[4];
    str = "192.168.1.1";
    sscanf(str,"%hhu.%hhu.%hhu.%hhu",&ip[0],&ip[1],&ip[2],&ip[3]);

上面的代码是我用来将 ip 地址值 存储到 char(uint8_t) array

【问题讨论】:

  • 格式应该是什么? 19216811?
  • 该值应等于0xc0a80101 十六进制值
  • @siva 我认为这就是我的解决方案将给你的......哈哈,现在才看到这个,有趣的是输出正是你想要的!好问题!

标签: c arrays scanf


【解决方案1】:

即使您的问题已经得到解答,但我非常喜欢您的问题,因此我决定解决它并为您实施解决方案。希望这能解决您的问题:

/**
 * The problem:
 *
 *    1 9 2 . 1 6 8 . 0 0 0 . 0 0 1
 *
 * How to store this in an int (32 bits)?
 *
 * Hum, let's see: 2^8 = 0-255 (stores values from 0 to 255)
 *
 *  2^(8 + 8 + 8 + 8) = 2^32 = sizeof(int) = 4 => nice!
 *
 * We can store four numbers from 0 to 255 in it, great!
 *
 *
 * Draft of solution:
 *
 * int ipaddress = 0; //0x00000000
 *
 * ipaddress = (192 << 32 - 8*1) || (168 << 32 - 8*2) || (0 << 32 - 8*3) || 1;
 *
 * classA_part = (ipaddress & 0xff000000) >> (32 - 8*1)
 * classB_part = (ipaddress & 0xff0000) >> (32 - 8*2)
 * classC_part = (ipaddress & 0xff00) >> (32 - 8*3)
 * classD_part = ipaddress & 0xff
 *
 * Let's implement shall we?!
 */

初步解决方案:

#define UPPER32 24
#define UPPER16 16
#define UPPER8  8

int main(void)
{
    int ipaddr = 192 << UPPER32 | 168 << UPPER16 | 0 << UPPER8 | 1; //192 168 000 001

    printf("ip address: %d.%d.%d.%d\n",
        ((ipaddr & 0xff000000) >> UPPER32) & 0xff,
        (ipaddr & 0xff0000) >> UPPER16,
        (ipaddr & 0xff00) >> UPPER8,
        (ipaddr & 0xff)
    );

    return 0;
}

请注意,由于您正在管理这些位以控制如何在其中存储内容,因此您需要将这些位移回它们在最低有效位中的位置,以便您真正获得您的值。

还要小心这部分((ipaddr &amp; 0xff000000) &gt;&gt; UPPER32) &amp; 0xff 这在没有&amp; 0xff 的机器上工作,因为我的机器是 64 位的,我的 64 位整数的扩展信号是 0,如果你的机器架构恰好是 32 位那么这会将 1 从第 31 位扩展到第 9 位,这是一个负数,因此您的 192 将是别的东西,甚至不会接近 192。

无论如何,通过使用0xff 的最终掩码,我们可以确保在 9 到 31 或 63 (x64) 的位中不会超过 0。

顺便说一句,这个输出将是:

ip address: 192.168.0.1
Program ended with exit code: 0

继续,请注意,按原样编写的代码对某些人来说可能很奇怪,并不是每个人都想处理位,因此通过简化我的初始解决方案可以实现更优雅的方法,请查看:

#define UPPER32 24
#define UPPER16 16
#define UPPER8  8

#define IPADDRESS(a,b,c,d)    (a << UPPER32 | b << UPPER16 | c << UPPER8 | d)
#define IPADDRESS_CLASS_A(ip) (((ip & 0xff000000) >> UPPER32) & 0xff)
#define IPADDRESS_CLASS_B(ip) ((ip & 0xff0000) >> UPPER16)
#define IPADDRESS_CLASS_C(ip) ((ip & 0xff00) >> UPPER8)
#define IPADDRESS_CLASS_D(ip) (ipaddr & 0xff)

#define IPADDRESS_FORMAT       "%d.%d.%d.%d"
#define EXTRACT_IPADDR(ip)     IPADDRESS_CLASS_A(ip), IPADDRESS_CLASS_B(ip), IPADDRESS_CLASS_C(ip), IPADDRESS_CLASS_D(ip)

int main(void)
{
    int ipaddr = IPADDRESS(192,168,0,1); //192 168 000 001
    printf("ip address: " IPADDRESS_FORMAT "\n", EXTRACT_IPADDR(ipaddr));
    return 0;
}

干净的版本看起来更好吧! 注意,参数a、b、c、d指的是ip地址的网络类别(A、B、C、D类)。

问候。

更新:

为了完美,用户(使用它的程序员)甚至不必担心 IP 地址的格式,因此,我添加了 IPADDRESS_FORMAT 宏,其中包含具有通用 IP 地址格式的字符串文字;) .

【讨论】:

    【解决方案2】:

    试试这个bit-shifting 方法将你的数组解析到一个内存位置。

    uint8_t ip[4];
    str = "192.168.1.1";
    sscanf(str,"%hhu.%hhu.%hhu.%hhu",&ip[0],&ip[1],&ip[2],&ip[3]);
    
    uint32_t ans = ip[0] << 24 + ip[1] << 16 + ip[2] << 8 + ip[3];
    

    【讨论】:

      【解决方案3】:

      您可能正在寻找inet_pton。或者你可以逃避这样的事情:

      uint32_t someint;
      uint8_t *ip = (void *)&someint;
      

      然后是你的sscanf

      【讨论】:

      • 工作,但它存储的值是相反的,所以我在打印时使用 htonl(someint),或者使用另一个变量以正确的方式存储它,例如(uint32_t anotherint = htonl (某些)
      • @siva 字节序。不如把订单改成ip[3], ip[2]...
      • 是的,我用过,但它的(htonl)有点熟悉
      • @downvoter 感谢您的反馈!也愿意发表评论吗?
      猜你喜欢
      • 2021-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-22
      相关资源
      最近更新 更多