【问题标题】:C UINT16 How to get it right?C UINT16 如何正确处理?
【发布时间】:2013-10-14 22:19:26
【问题描述】:

我是 C 编程新手,我正在测试一些代码,我在其中接收和处理格式如下的 UDP 数据包:

UINT16 port1
UINT16 port2

本次测试对应的值为:

6005
5555

如果我打印整个数据包缓冲区,我会得到这样的结果:

u^W³^U><9e>^D

所以我认为我只需要打破它并将其处理为 16 个字节的unsigned int。所以我尝试了这样的事情:

int l = 0;
unsigned int *primaryPort = *(unsigned int) &buffer[l]; 
AddToLog(logInfo, "PrimaryPort: %u\n", primaryPort);
l += sizeof(primaryPort);
unsigned int *secondaryPort = *(unsigned int) &buffer[l]; 
AddToLog(logInfo, "SecondaryPort: %u\n", secondaryPort);
l += sizeof(secondaryPort);

但我得到了错误的 8 位数字。

我什至尝试了另一种方法,例如跟随,但也得到了错误的数字。

int l = 0;
unsigned char primaryPort[16]; 
snprintf(primaryPort, sizeof(primaryPort), "%u", &buffer[l]);
AddToLog(logInfo, "PrimaryPort: %d\n", primaryPort);
l += sizeof(primaryPort);
unsigned char secondaryPort[16]; 
snprintf(secondaryPort, sizeof(secondaryPort), "%u", &buffer[l]);
AddToLog(logInfo, "SecondaryPort: %d\n", secondaryPort);
l += sizeof(secondaryPort);

我做错了什么?另外,为什么我必须释放 char 字符串变量,但不需要释放 int 变量?

【问题讨论】:

  • 如果你问的是C,为什么标签里有C++和C#?
  • 很可能,在您的系统上unsigned int 实际上不是一个 16 位整数,而sizeof(unsigned int) != 2。而*(unsigned int) &buffer[l] 没有任何意义(并且无法编译):您将指针转换为整数,然后尝试取消引用所述整数。
  • "另外,为什么我必须释放 char 字符串变量,但不需要释放 int 变量?"是否必须调用free 与变量的类型无关。
  • 我有根据的猜测是,你想要这样的东西:unit16_t primaryPort = ntohs(*(unit16_t*)&buffer[0]); unit16_t secondaryPort = ntohs(*(unit16_t*)&buffer[2]);

标签: c int uint16


【解决方案1】:

您将传递给AddToLogsnprintf 指向整数的指针。所以你看到的是整数的地址,而不是整数本身。

您需要取消引用您的指针 - 例如,在您的第一种方法中调用 AddToLog 时,在 primaryPort 前面加上一个星号 (*)。

正如@rileyberton 建议的那样,unsigned int 在您的系统上很可能是 4 个字节,即 C99 类型 uint32_t。对于 16 位整数,请使用 uint16_t。这些在stdint.h 中定义。这些传统上称为“短整数”或“半整数”,需要在printf 或类似函数中使用%hu 限定符,而不仅仅是%u(代表unsigned int,其大小取决于目标机器。 )

另外,正如@igor-tandetnik 建议的那样,您可能需要切换数据包中整数的字节顺序,例如,如果数据包使用网络顺序(大端)格式并且您的目标机器使用 little-字节序格式。

【讨论】:

    【解决方案2】:

    您系统上的 unsigned int 可能是 4 个字节 (uint32_t)。如果您屏蔽了正确字节序中的值,则可以在此处使用 unsigned int,或者仅使用短字节。

    int l = 0;
    unsigned short *primaryPort = *(unsigned short) &buffer[l]; 
    AddToLog(logInfo, "PrimaryPort: %u\n", primaryPort);
    l += sizeof(*primaryPort);
    unsigned short *secondaryPort = *(unsigned short) &buffer[l]; 
    AddToLog(logInfo, "SecondaryPort: %u\n", secondaryPort);
    l += sizeof(*secondaryPort);
    

    【讨论】:

    • 或者一个..你知道..uint16_t.
    【解决方案3】:

    您将primaryPortsecondaryPort 声明为指向unsigned short 的指针。

    但是,当您从缓冲区的一部分中为它们分配值时,您已经取消了对指针的引用。你不需要pointers-to-unsigned-short。你只需要一个unsigned short

    改成:

    unsigned short primaryPort = *((unsigned short*) &buffer[l]); 
    
    unsigned short secondaryPort = *((unsigned short *) &buffer[l]); 
    

    注意在变量声明中删除了*

    如果您仍然遇到问题,则需要逐字节检查buffer,寻找您期望的值。您可以预期 6005 将显示为十六进制 17 7575 17,具体取决于您平台的 endianness

    【讨论】:

      猜你喜欢
      • 2011-02-16
      • 1970-01-01
      • 2012-03-26
      • 2017-01-31
      • 1970-01-01
      • 1970-01-01
      • 2013-11-19
      • 1970-01-01
      • 2016-04-09
      相关资源
      最近更新 更多