【指针】01.指针强转,指针的指针,指针与常量/数组
【嵌入式八股】一、语言篇(本专栏)https://www.nowcoder.com/creation/manager/columnDetail/mwQPeM
【嵌入式八股】二、计算机基础篇https://www.nowcoder.com/creation/manager/columnDetail/Mg5Lym
【嵌入式八股】三、硬件篇https://www.nowcoder.com/creation/manager/columnDetail/MRVDlM
【嵌入式八股】四、嵌入式Linux篇https://www.nowcoder.com/creation/manager/columnDetail/MQ2bb0
一、C/C++ 03.指针
指针类型转换
01.指针类型转换
int num=0x12345678;
int* p=#
char* c=(char *)p; //把p的 int* 类型 强转为 char* 类型
//最好把类型转换加上,否则有些编译器会报错
printf("%x %x",*p,*c); //输出*p和num一样,输出*c是78(和数据保存的大小端模式有关)
//(int *)p 如果把char *的强转为int型的会报错,因为定义char类型数据只分配了一个字节,强转为int型会多出三个字节的没有分配的地址
02.指针进行强制类型转换后与地址进行加法运算,结果是什么?
假设在32位机器上,在对齐为4的情况下,sizeof(long)的结果为4字节,sizeof(char*)的结果为4字节, sizeof(short int)的结果与 sizeof(short)的结果都为2字节, sizeof(char)的结果为1字节, sizeof(int)的结果为4字节,由于32位机器上是4字节对齐,以如下结构体为例:
struct BBB {
long num; //4
char *name; //4
short int data;//2
char ha; //1
short ba[5]; //10
}*p;
//当p=0x100000; 则p+0×200=? (char*)p+0x200=? (ulong)p+0x200=?
解答:
在32位机器下, sizeof(struct BBB)=sizeof(*p)=4+4+2+1+3/*补齐*/+2*5+2/*补齐*/=24字节,
指针加法,加出来的是指针所指类型(结构体类型)的字节长度的整倍数,就是p偏移sizeof(p)*0x200。
而p=0x100000,那么p+0x200=0x1000000+0x200*24
(char*)p+0x200=0x1000000+0×200*sizeof(char) 结果类型是char*。
(ulong)p+0x200=0x10000010+0x200 经过ulong后,已经不再是指针加法,而变成一个数值加法了。
指针的指针
int num; //定义变量,变量类型是 int
int* pt=# //定义指针, 其指向的类型是 int
int** ppt=&pt; //定义指针的指针,它指向的是指针(其指向的类型是 int)
//int *(*ppt); 优先级 从右到左
// int *pt; pt == *ppt; 替换法(用pt替代*ppt ,则ppt是指向pt的指针)
03.指针的指针用途
指针的指针具有以下用途:
-
**动态分配内存:**使用指针的指针可以动态分配内存并将其传递给函数,以便函数可以修改指向该内存的指针。这样可以避免在函数中使用全局变量,提高程序的模块化程度。
#include <stdio.h> #include <stdlib.h> void allocate_memory(int** pptr) { *pptr = (int*)malloc(sizeof(int)); **pptr = 10; } int main() { int* ptr; allocate_memory(&ptr); printf("%d\n", *ptr); free(ptr); return 0; }
在上面的示例中,函数
allocate_memory
接受一个指向指针的指针pptr
,并将一个指向动态分配的内存的指针赋值给它。在main
函数中,我们声明了一个指向int
类型的指针ptr
,并将其作为参数传递给allocate_memory
函数,从而将指向动态分配的内存的指针传递回来。最后我们输出指针指向的内存的值并释放内存。 -
函数参数传递:指针的指针也可以被用来传递函数参数。在C语言中,函数参数默认是按值传递的,这意味着在函数中修改参数的值不会影响调用方的参数。但是如果将指向指针的指针作为函数参数,就可以在函数内部修改指针的指针指向的内存,从而影响调用方的指针。
#include <stdio.h> #include <stdlib.h> void change_ptr(int **ptr_ptr) { int *ptr = malloc(sizeof(int)); *ptr = 100; *ptr_ptr = ptr; } int main() { int num = 10; int *ptr = # printf("ptr points to value: %d\n", *ptr); change_ptr(&ptr); printf("ptr now points to value: %d\n", *ptr); free(ptr); return 0; }
在这个示例代码中(其实和第一个一样),我们使用
malloc
函数动态分配了一块内存,并将值100存储在这块内存中。然后将指向该内存的指针赋值给指向指针的指针,从而在函数返回后,ptr
仍然可以访问该内存中存储的值。最后我们使用free
函数释放了分配的内存。这个示例代码展示了如何使用指向指针的指针来传递函数参数,并在函数内部动态分配内存并返回指向该内存的指针。这种技巧可以被用于很多不同的应用场景,例如实现动态数组、动态链表等数据结构。
-
二维数组/多级访问:指针的指针可以被用来处理二维数组。在C语言中,二维数组实际上是一个连续的内存块,可以通过指向指针的指针来处理。通过指向指针的指针,可以实现对二维数组中每个元素的动态访问。
#include <stdio.h> int main() { int a[2][3] = {{1, 2, 3}, {4, 5, 6}}; int (*pptr)[3] = a; // 指向指针的指针【数组指针】 printf("%d\n", *(*pptr + 1)); // 输出第一行第二个元素 2 printf("%d\n", *(*(pptr+1) + 1)); // 输出第二行第二个元素 5 return 0; }
在上面的示例中,我们声明了一个二维数组
a
,并将其赋值给一个指向指针的指针pptr
。由于pptr
是指向int[3]
类型的指针,因此可以使用*pptr
获取指向第一行的指针,使用*(*pptr + 1)
获取第一行第二个元素的值。 -
链表:链表是一个常见的数据结构,使用指针的指针可以在链表的添加、删除等操作中起到重要作用。
#include <stdio.h> #include <stdlib.h> struct node { int data; struct node* next; }; void add_node(struct node** head_ref, int new_data) { struct node* new_node = (struct node*)malloc(sizeof(struct node)); new_node->data = new_data; new_node->next = *head_ref; *head_ref = new_node; }
04.指针的指针用于函数传参中的传入传出参数
传入参数:
1. 指针作为函数参数。
2. 同常有const关键字修饰。
3. 指针指向有效区域, 在函数内部做读操作。
传出参数:
1. 指针作为函数参数。
2. 在函数调用之前,指针指向的空间可以无意义,但必须有效。
3. 在函数内部,做写操作。
4。函数调用结束后,充当函数返回值。
传入传出参数:
-
指针作为函数参数。
-
在函数调用之前,指针指向的空间有实际意义。
-
在函数内部,先做读操作,后做写操作。
-
函数调用结束后,充当函数返回值。
库函数strtok示意:
char *strtok(char *str, const char *delim) //分解字符串 str 为一组字符串,delim 为分隔符。
//函数strtok_r是函数strtok的可重入版本,也即线程安全版本。在函数strtok中剩余字符串是存储在一个静态变量中,因此,多线程在使用该静态变量时引起冲突;而strtok_r则使用用户传入的指针为每个用户saveptr重新申请变量,因而可以保证线程安全。
char *strtok_r(char *str, const char *delim, char **saveptr); //主要作用是按某个字符来分割字符串
//char *str 传出参数
//const char *delim 传入参数
//char **saveptr 传入传出参数,(传进来改了传出去)双指针
char *str是被分割字符串
const char *delim是分隔符,
char **saveptr是一个供内部使用的指针,用于保存上次分割剩下的字串。
返回值是个指针,用于返回从被分割字
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
查阅整理上千份嵌入式面经,将相关资料汇集于此,主要包括: 0.简历面试 1.语言篇【本专栏】 2.计算机基础 3.硬件篇 4.嵌入式Linux (建议PC端查看)