C Tips:需要注意的地方

C语言结构体与指针详解
本文深入探讨了C语言中的结构体声明与使用、文件读写操作、指针运算及内存管理等内容,包括结构体定义、类型定义、文件读写函数、指针算术等关键知识点。

结构体声明:

struct classA {...};      // struct classA x1;
typedef struct {...} classB; // classB x2;
typedef struct classA {...} classC; // classC x3;   <==> struct classA x3;
classA的定义必须加struct结构标签;用typedef进行类型定以后,classB可直接用于定义;classC的定义两种方法均可使用。

文件读写结构体:

fwrite(&somestruct, sizeof somestruct, 1, fp);
fread(&somestruct, sizeof somestruct, 1, fp);

不需要临时变量,交换a,b值

// 根据方法 1,同理可推出其他方式
a = a + b;
b = a - b;
a = a - b;

后缀++和--操作符比前缀一元操作符高

*p ++; // 等价于 *(p++)

C语言中没有通用的指针类型

// 用void **通用指针作为参数,但不可移植
void func(void **); 
double *dp;
func((void **)&dp); 

char a[] 和 char *p不等价

char a[] = "hello";  // a 即为"hello"字符串 , a[i] = 'p' 可以更改
char *p = "world";   // p 存取"world"的地址 , p[i] = 'p' 不可更改 , 属于无名的静态数组

调用free()后,指针指向的内存被释放,但指针并没有置空,最后在释放之后立即将它们置为NULL,以明确状态。

sizeof()不能告知指针所指内存的大小,只能得到指针本身的大小。实际上,没有什么可移植的方法得到malloc()函数分配的内存块大小。

calloc()和malloc()的区别:

p = calloc(m, n); 

<==>

p = malloc( m * n );
memset(p, 0, m * n);

C语言中字符常量是int类型,与C++不同,C++中为char类型

int conLen = sizeof('a') ;   // 4
int intLen = sizeof(int);    // 4
int charLen = sizeof(char);  // 1

// 前两个可以互换,表示*p的值为可读
// 第三个指的是指针p不可修改,属于指针常量
const char *p;
char const *p;
char * const p;

把stdin或stdout重定向到文件,stdout/stdin为常量,因此不能进行赋值;一旦使用freopen后,无法恢复到原来的stdout/stdin,因此最好一开始就不要用

FILE *saveStdout = stdout;
freopen(fileName, "w", stdout);
stdout = fopen(fileName, "w"); // wrong
stdout = saveStdout; // wrong



type = MQTT_UnPacketRecv(cmd); switch (type) { case MQTT_PKT_CMD: // 命令下发 result = MQTT_UnPacketCmd(cmd, &cmdid_topic, &req_payload, &req_len); // 解出topic和消息体 if (result == 0) { UsartPrintf(USART_DEBUG, "cmdid: %s, req: %s, req_len: %d\r\n", cmdid_topic, req_payload, req_len); if (MQTT_PacketCmdResp(cmdid_topic, req_payload, &mqttPacket) == 0) // 命令回复组包 { UsartPrintf(USART_DEBUG, "Tips: Send CmdResp\r\n"); ESP8266_SendData(mqttPacket._data, mqttPacket._len); // 回复命令 MQTT_DeleteBuffer(&mqttPacket); // 删包 } } break; case MQTT_PKT_PUBLISH: // 接收的Publish消息 result = MQTT_UnPacketPublish(cmd, &cmdid_topic, &topic_len, &req_payload, &req_len, &qos, &pkt_id); if (result == 0) { UsartPrintf(USART_DEBUG, "topic: %s, topic_len: %d, payload: %s, payload_len: %d\r\n", cmdid_topic, topic_len, req_payload, req_len); switch (qos) { case 1: // 收到publish的qos为1,设备需要回复Ack if (MQTT_PacketPublishAck(pkt_id, &mqttPacket) == 0) { UsartPrintf(USART_DEBUG, "Tips: Send PublishAck\r\n"); ESP8266_SendData(mqttPacket._data, mqttPacket._len); MQTT_DeleteBuffer(&mqttPacket); } break; case 2: // 收到publish的qos为2,设备先回复Rec // 平台回复Rel,设备再回复Comp if (MQTT_PacketPublishRec(pkt_id, &mqttPacket) == 0) { UsartPrintf(USART_DEBUG, "Tips: Send PublishRec\r\n"); ESP8266_SendData(mqttPacket._data, mqttPacket._len); MQTT_DeleteBuffer(&mqttPacket); } break; default: break; } } break; case MQTT_PKT_PUBACK: // 发送Publish消息,平台回复的Ack if (MQTT_UnPacketPublishAck(cmd) == 0) UsartPrintf(USART_DEBUG, "Tips: MQTT Publish Send OK\r\n"); break; case MQTT_PKT_PUBREC: // 发送Publish消息,平台回复的Rec,设备需回复Rel消息 if (MQTT_UnPacketPublishRec(cmd) == 0) { UsartPrintf(USART_DEBUG, "Tips: Rev PublishRec\r\n"); if (MQTT_PacketPublishRel(MQTT_PUBLISH_ID, &mqttPacket) == 0) { UsartPrintf(USART_DEBUG, "Tips: Send PublishRel\r\n"); ESP8266_SendData(mqttPacket._data, mqttPacket._len); MQTT_DeleteBuffer(&mqttPacket); } } break; case MQTT_PKT_PUBREL: // 收到Publish消息,设备回复Rec后,平台回复的Rel,设备需再回复Comp if (MQTT_UnPacketPublishRel(cmd, pkt_id) == 0) { UsartPrintf(USART_DEBUG, "Tips: Rev PublishRel\r\n"); if (MQTT_PacketPublishComp(MQTT_PUBLISH_ID, &mqttPacket) == 0) { UsartPrintf(USART_DEBUG, "Tips: Send PublishComp\r\n"); ESP8266_SendData(mqttPacket._data, mqttPacket._len); MQTT_DeleteBuffer(&mqttPacket); } } break; case MQTT_PKT_PUBCOMP: // 发送Publish消息,平台返回Rec,设备回复Rel,平台再返回的Comp if (MQTT_UnPacketPublishComp(cmd) == 0) { UsartPrintf(USART_DEBUG, "Tips: Rev PublishComp\r\n"); } break; case MQTT_PKT_SUBACK: // 发送Subscribe消息的Ack if (MQTT_UnPacketSubscribe(cmd) == 0) UsartPrintf(USART_DEBUG, "Tips: MQTT Subscribe OK\r\n"); else UsartPrintf(USART_DEBUG, "Tips: MQTT Subscribe Err\r\n"); break; case MQTT_PKT_UNSUBACK: // 发送UnSubscribe消息的Ack if (MQTT_UnPacketUnSubscribe(cmd) == 0) UsartPrintf(USART_DEBUG, "Tips: MQTT UnSubscribe OK\r\n"); else UsartPrintf(USART_DEBUG, "Tips: MQTT UnSubscribe Err\r\n"); break; default: result = -1; break; } ESP8266_Clear(); // 清空缓存 if (result == -1) return; dataPtr = strchr(req_payload, '}'); // 搜索'}' if (dataPtr != NULL && result != -1) // 如果找到了 { dataPtr++; while (*dataPtr >= '0' && *dataPtr <= '9') // 判断是否是下发的命令控制数据 { numBuf[num++] = *dataPtr++; } num = atoi((const char *)numBuf); // 转为数值形式 } if (type == MQTT_PKT_CMD || type == MQTT_PKT_PUBLISH) { MQTT_FreeBuffer(cmdid_topic); MQTT_FreeBuffer(req_payload); } } 解析这个代码
03-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值