簡體   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