You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中将uint16_t数组转换为逗号分隔char数组问题咨询

问题根因分析
  • 最初代码错误:直接把数组名status传给sprintf的%u格式符,数组名本质是数组首地址的指针,所以输出的是内存地址数值而非数组元素值
  • 逐元素拼接版本两个错误:
    1. 函数内重复定义了局部uint16_t status[sz]数组,覆盖了全局已经读取到数据的status数组,局部数组未初始化值为随机垃圾值
    2. 拼接完成后指针p已经移动到了字符串末尾的结束符位置,调用publish传入p相当于传入空字符串
正确实现方案
// 保持全局的status数组定义不变
uint16_t status[8];
long lastMsg = 0;

void loop() {
  mb.task();
  yield();
  
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  long now = millis();
  if (now - lastMsg > 3000) {
    lastMsg = now;
    // 读取寄存器到全局status数组
    mb.readHreg(SLAVE_ID, 0x0001, status, 8, cbWrite); 
    
    // 定义足够大的缓冲区,单个uint16_t最大是5位数字+逗号空格,8个最多占56字节,开80足够
    char str[80] = {0}; // 初始化为0避免乱码
    char* p = str;
    int offset;
    
    // 拼接第一个元素
    offset = sprintf(p, "%u", status[0]);
    p += offset;
    
    // 拼接后续元素,前面加逗号空格
    for (int i = 1; i < 8; i++) {
      offset = sprintf(p, ", %u", status[i]);
      p += offset;
    }
    
    // 传入字符串首地址str,而非移动后的指针p
    client.publish("device1/relaysChannelStatus", str);
  }
}
简化实现方案

如果担心sprintf缓冲区溢出,也可以直接用Arduino原生String类拼接,代码更简洁:

// 读取寄存器后的拼接逻辑
String payload = String(status[0]);
for (int i = 1; i < 8; i++) {
  payload += ", " + String(status[i]);
}
client.publish("device1/relaysChannelStatus", payload.c_str());

内容的提问来源于stack exchange,提问作者xxxbud

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 10:27:03