本次博客知识来自于韦东山老师的7天物联网课程。
1、当使用HAL库的函数时,遇到函数形参时指针时,实参应为地址。
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
这个函数中,形参UART_HandleTypeDef *huart、uint8_t *pData。均为指针,所以调用时,实参应为地址,如下。
HAL_UART_Receive_IT(&huart2, (uint8_t*)&rx_data, 1);
2、强制数据类型转换。
如上,(uint8_t*)&rx_data,即为把rx_data强制转换为8位的指针并取地址。
3、数组地址的问题。
数组名即可代表数组首元素的地址。
详细解释见数组的地址问题详解。
4、字符串地址的问题。
字符串本身就是一个地址,字符串它的本身就相当于字符数组名,数组可以的操作,字符串也都可以。详细解释见字符串的地址问题详细解释。
如下代码,函数的形参是指针,而实参用的是字符串。
ESP8266_SendCommand("AT+CWMODE=1", "OK", 500);
uint8_t ESP8266_SendCommand(char *cmd, char *reply, uint16_t timeout)
#include <stdio.h>
#include<string.h>
using namespace std;
int main()
{
char c[5] = {1,2,3,4,5};
printf("%#x\n", c);
printf("%#x\n", &c[0]);
printf("%#x\n", &c);
printf("\n");
printf("%#x\n", &c[1]);
printf("%#x\n", c + 1);
printf("%#x\n", &c[0]+1);
printf("%#x\n", &c+1);
printf("%#x\n", (&c) + 1);
printf("%d\n", sizeof(c[0]));
printf("%d\n", sizeof(c));
printf("%d\n", sizeof(&c[0]));
printf("%d\n", sizeof(&c));
printf("%d\n", sizeof(char));
printf("%d\n", sizeof(int));
}
/* printf example */
#include <stdio.h>
#include<string.h>
using namespace std;
int main()
{
char c[4] = {1,2,3,4};
printf("%#x\n", c);
printf("%#x\n", &c[0]);
printf("%#x\n", &c);
printf("\n");
printf("%#x\n", &c[1]);
printf("%#x\n", c + 1);
printf("%#x\n", &c[0]+1);
printf("%#x\n", &c+1);
printf("%#x\n", (&c) + 1);
printf("%d\n", sizeof(c[0]));
printf("%d\n", sizeof(c));
printf("%d\n", sizeof(&c[0]));
printf("%d\n", sizeof(&c));
printf("%d\n", sizeof(char));
printf("%d\n", sizeof(int));
}
结合上述两个程序,得到
- c是数组首元素地址0x49eff9b4;
- c+1为数组元素地址后移一个char型(1个char型一个字节)的偏移量0x49eff9b4+1;
- &c是整个数组的地址0x49eff9b4;
- &c+1、((&c)+1)整个数组的地址后移整个数组空间大小的偏移量,即0x49eff9b4+1*4=0x49eff9b9或0x49eff9b4+1*3=0x49eff9b8;
- &c[0]是数组首元素地址0x49eff9b4,注意:&c[0]是一个指针,编译器要为它分配存储空间,但c不是指针型变量,不会被分配存储空间;
- &c[0]+1为数组元素地址后移一个char型的偏移量,即0x49eff9b4+1;
- sizeof(c[0])是首元素1所占字节大小:1;
- sizeof(c)是整个数组所占字节大小:4*1/5*1;
- sizeof(&c)是数组的地址所占字节大小:8;
- sizeof(&c[0])是首元素1的地址所占字节大小:8;
- sizeof(char)、sizeof(int)分别是char型和整形所占的字节大小。
5、printf输出格式。
如,printf("%d\n", a)中,%d即为a表示的输出位置,且是用10进制的格式输出。
详细的解释见详细printf()输出格式。
6、取余的巧妙用法。
static uint8_t rx_data = 0; //接收的字符
static uint8_t rx_len = 0; //接收的长度
static uint8_t usart_rx_buf[200] = {0};//保存接收的数据
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
usart_rx_buf[rx_len%200]= rx_data;
rx_len++;
HAL_UART_Receive_IT(&huart2, (uint8_t*)&rx_data, 1);
}
上述代码中usart_rx_buf[]为一个200个成员的数组,但是第五行代码用了rx_len%200,取余的操作,巧妙的解决了容量不足的问题,思路如下。
1/200=余1
2/200=余2
201/200=余1
202/200=余2
7、memcpy、memset、strcat、strstr、sprintf。
1)memcpy
extern void *memcpy(void *dest, void *src, unsigned int count);
用法:#include <string.h>
功能:由src所指内存区域复制count个字节到dest所指内存区域。
说明:
- str1 -- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针;
- str2 -- 指向要复制的数据源,类型强制转换为 void* 指针;
- n -- 要被复制的字节数。
-
src和dest所指内存区域不能重叠,函数返回指向dest的指针。
2)memset
void *memset(void *str, int c, size_t n)
用法:#include <string.h>
功能:复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字节。
说明:
- str -- 指向要填充的内存块;
- c -- 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式;
- n -- 要被设置为该值的字节数;
- 该值返回一个指向存储区 str 的指针。
3)strcat
char *strcat(char *dest, const char *src)
用法:#include <string.h>
功能:把 src 所指向的字符串拼接到 dest 所指向的字符串的结尾。
说明:
- dest -- 指向目标数组,该数组包含了一个 C 字符串,且足够容纳追加后的字符串;
- src -- 指向要追加的字符串,该字符串不会覆盖目标字符串;
- 该函数返回一个指向最终的目标字符串 dest 的指针。
4)strstr
char *strstr(const char *haystack, const char *needle)
用法:#include <string.h>
功能:在字符串 haystack 中查找第一次出现字符串 needle 的位置,不包含终止符 '\0'。
说明:
- haystack -- 要被检索的 C 字符串;
- needle -- 在 haystack 字符串内要搜索的小字符串;
-
该函数返回在(返回值) haystack 中第一次出现 needle 字符串的地址,如果未找到则返回 null。
5)sprintf
int sprintf(char *buffer, const char *format, [argument]…)
用法:#include <stdio.h>
功能:格式化字符串,将格式化的数据写入字符串中。
说明:
- buffer -- 是char类型的指针,指向写入的字符串指针;
- format -- 格式化字符串,即在程序中想要的格式;
-
argument -- 可选参数,可以为任意类型的数据;
-
函数返回值:buffer指向的字符串的长度。
-
格式化数字字符串:在这点上sprintf和printf的用法一样,只是打印到的位置不同而已,前者打印给buffer字符串,后者打印给标准输出,所以sprintf也可以用来将整型转化为字符串,比itoa效率高且如此地简便~比如:sprintf(buffer, “%d”, 123456);执行后buffer即指向字符串“123456”~
-
#include<stdio.h> int main() { char buffer[10]; char *a = “1234”; char *b = “5678”; sprintf(buffer, ”%s%s”, a, b); printf(”%s\n”, buffer); return 0; }
结果