繁体   English   中英

如何从 uint32_t 获取浮点值?

[英]How to get float value from uint32_t?

我使用这部分代码从我的微控制器上的 OSC 消息中读取浮点值。 但是我得到“取消引用类型双关指针将破坏严格别名规则[-Wstrict-aliasing]”错误并且printf上没有显示任何值。 这个有什么解决方法吗? 标记在结构中为:

char *marker;  // the current read head
float tosc_getNextFloat(tosc_message *o) {
  // convert from big-endian (network btye order)
  const uint32_t i = ntohl(*((uint32_t *) o->marker));
  o->marker += 4;
  return *((float *) (&i));  <---- this line of code does the error
}

编辑 :

因此,我使用以下函数通过 udp 从微控制器互联网芯片接收数据:

datasize_t recvfrom(uint8_t sn, uint8_t * buf, datasize_t len, uint8_t * addr, uint16_t *port, uint8_t *addrlen) //<- general 

然后我运行另一个函数来解析 osc 消息:

tosc_parseMessage(&A, (char*) buf, received_size); //<- how i wrote parameters

其中 A 是结构:

 typedef struct tosc_message {
    char *format;  // a pointer to the format field
    char *marker;  // the current read head
    char *buffer;  // the original message data (also points to the address)
    uint32_t len;  // length of the buffer data
} tosc_message;

和 tosc_parseMessage 是:

int tosc_parseMessage(tosc_message *o, char *buffer, const int len) {
  // NOTE(mhroth): if there's a comma in the address, that's weird
  int i = 0;
  while (buffer[i] != '\0') ++i; // find the null-terimated address
  while (buffer[i] != ',') ++i; // find the comma which starts the format string
  if (i >= len) return -1; // error while looking for format string
  // format string is null terminated
  o->format = buffer + i + 1; // format starts after comma

  while (i < len && buffer[i] != '\0') ++i;
  if (i == len) return -2; // format string not null terminated

  i = (i + 4) & ~0x3; // advance to the next multiple of 4 after trailing '\0'
  o->marker = buffer + i;

  o->buffer = buffer;
  o->len = len;

  return 0;
}

然后我打印出来:

void tosc_printMessage(tosc_message *osc) {
  printf("[%i bytes] %s %s",
      osc->len, // the number of bytes in the OSC message
      tosc_getAddress(osc), // the OSC address string, e.g. "/button1"
      tosc_getFormat(osc)); // the OSC format string, e.g. "f"

  for (int i = 0; osc->format[i] != '\0'; i++) {
    switch (osc->format[i]) {
      case 'f': printf(" %g", tosc_getNextFloat(osc)); break;
      case 'd': printf(" %g", tosc_getNextDouble(osc)); break;
      case 'i': printf(" %d", tosc_getNextInt32(osc)); break;
      default: printf(" Unknown format: '%c'", osc->format[i]); break;
    }
  }
  printf("\n");
}

我的问题在于功能:

float tosc_getNextFloat(tosc_message *o) {
  // convert from big-endian (network btye order)
  const uint32_t i = ntohl(*((uint32_t *) o->marker));
  o->marker += 4;
  return *((float *) (&i));  <---- this line of code does the error
}

我希望这能让你更好地了解问题......我不是熟练的程序员,所以我感谢任何帮助。 这个“库”的完整代码可以在这里找到https://github.com/mhroth/tinyosc ,我只是想在我的微控制器中实现它

float tosc_getNextFloat(tosc_message *o) {
  // convert from big-endian (network btye order)
  const uint32_t i = ntohl(*((uint32_t *) o->marker));
  o->marker += 4;

  float tmp = 0;
  memcpy((void *)&tmp, (void *)&i, sizeof(uint32_t));
  return tmp;
}

如果需要类型双关,最好使用配置为支持它的编译器(在一些非商业设计的编译器上,但不是商业设计的,这意味着使用-fno-strict-aliasing )而不是跳过箍以适应拒绝通过明显新派生的指针识别类型双关的编译器编写者。

C 实现有时用于类型双关有用的目的,有时用于无用的目的。 该标准的作者认识到编译器编写者应该比委员会更了解他们个人客户的需求,因此允许实现支持最​​适合其客户需求的任何构造组合。 不知何故,出现了一个神话,即标准将其描述为“损坏的”程序,该程序依赖于实现以“以环境特征的文档化方式”处理它们,但任何此类阅读都直接与标准作者的陈述意图相矛盾。

毕竟不是代码问题。 是的,我仍然收到该警告(但代码有效)。 实际问题出在 IDE 中。 在构建器设置中的链接器设置中,需要添加: -u _printf_float 。 那花了我生命中的一个月才弄清楚发生了什么。 谢谢大家的回答

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM