C 如何从uint32\t获取浮点值?

C 如何从uint32\t获取浮点值?,c,strict-aliasing,type-punning,C,Strict Aliasing,Type Punning,我使用这部分代码从微控制器上的OSC消息中读取浮点值。然而,我得到了“取消引用类型punned指针将破坏严格的别名规则[-Wstrict aliasing]”错误,并且printf上没有显示任何值。这个有什么解决办法吗?标记位于结构中,如下所示: char *marker; // the current read head 而tosc_的信息是: int tosc_parseMessage(tosc_message *o, char *buffer, const int len) { /

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

char *marker;  // the current read head
而tosc_的信息是:

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;
}
我的问题在于功能:

datasize_t recvfrom(uint8_t sn, uint8_t * buf, datasize_t len, uint8_t * addr, uint16_t *port, uint8_t *addrlen) //<- general 
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
}
float tosc_getNextFloat(tosc_消息*o){
//从big-endian转换(网络B字节订单)
常数uint32_t i=ntohl(*(uint32_t*)o->marker);
o->marker+=4;

return*((float*)(&i));如果需要类型双关,最好使用配置为支持它的编译器(在一些非商业设计的编译器上,而不是商业设计的编译器上,这意味着使用
-fno严格的别名
)而不是为了适应那些拒绝通过明显新派生的指针识别类型双关的编译器编写者而跳转


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

毕竟这不是代码问题。是的,我仍然得到了警告(但代码有效)。实际问题在IDE中。在链接器设置和生成器设置中,需要添加:-u\u printf\u float。这花了我一个月的时间才弄清楚发生了什么。感谢大家回答这条消息到底指的是哪一行?这是否回答了您的问题?或者这可能是您想要的:
return(float)i;
?我已经尝试了所有这些,但输出上仍然没有值,所以,可能输入是空的:)我在考虑由“o”指向的缓冲区。我应该得到如下值:056487 083412,我连接的程序正在发送它(我可以通过osc监视器看到)你现在得到了什么?总是0?检查缓冲区*o-它是如何填充的?数据是如何写入的?给我们看代码。我已经通过printf%c我的缓冲区得到了一些东西…为了得到0.59088的值,我有下一个十六进制数(逐字节)“?ETB c xBA”(这应该是3F 17 43 e9,我看过浮点到十六进制转换器)…完整信息是:/composition/crossfader/phaseNULNULNUL,fNULNUL?etbcxbanulnulnulnulnulnul(如notepad++)经过一些调查后,它应该是0.590877..所以浮点十六进制是“3f 17 43 ba”,不知怎的,一个神话出现了,标准将其描述为依赖于实现来处理它们的“坏”程序“以一种记录在案的环境特征”IMO这更像是对“它能工作,所以它必须是好的”编码者的一种反应,他们不知道他们正在违反规则,因为他们的平台允许他们逃脱。只需谷歌“SIGBUS ARM”或“SIGBUS SPARC”“当他们得知
return*((float*)(&i))
会爆炸时,请注意一些惊愕和惊讶。@AndrewHenle:code依赖于“记录的环境特征行为”当在具有适当特征行为的环境中运行时,应仅期望能按预期工作。另一方面,大多数代码只会被调用在具有某些特定已知特征的执行环境中运行。C之所以流行和有用的原因之一是,简单实现可以允许程序员利用程序员知道的目标环境的特征,而实现不必了解它们。@AndrewHenle:只要看一下您查询的初始命中率,就可以知道代码试图从未对齐的地址加载浮点数。代码需要在没有对齐的平台上运行如果不允许这样的加载,则在加载数据之前需要将数据复制到正确对齐的位置,但这并不意味着在访问对齐方式已满足目标要求的对象时,需要进行这样的复制。@AndrewHenle:当标准规定,指定失败与否在强调上没有区别时一个动作的行为和一个动作调用未定义行为的语句,如果标准没有在所有硬件上指定一个普通动作类的行为,但是标准的一部分结合实现的文档将描述一个动作的行为,那么应该如何解释标准的其他部分将其划分为UB。如果没有标准的后一部分,行为将被定义……即使标准本身没有定义它。一些编译器作者似乎认为“强调没有区别”意味着“UB的特性胜过一切”.我自己的解释是,在发生此类冲突的情况下,优先级需要由标准之外的内容来确定(例如,什么最适合为客户服务,什么最适合为不关心为客户服务的假设编译器编写者的突发奇想服务,等等)您能否对该标准的意图做出更合理的解释?
 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;
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
}
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;
}