【指针】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

alt

一、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.指针的指针用途

指针的指针具有以下用途:

  1. **动态分配内存:**使用指针的指针可以动态分配内存并将其传递给函数,以便函数可以修改指向该内存的指针。这样可以避免在函数中使用全局变量,提高程序的模块化程度。

    #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函数,从而将指向动态分配的内存的指针传递回来。最后我们输出指针指向的内存的值并释放内存。

  2. 函数参数传递:指针的指针也可以被用来传递函数参数。在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 = &num;
        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函数释放了分配的内存。

    这个示例代码展示了如何使用指向指针的指针来传递函数参数,并在函数内部动态分配内存并返回指向该内存的指针。这种技巧可以被用于很多不同的应用场景,例如实现动态数组、动态链表等数据结构。

  3. 二维数组/多级访问:指针的指针可以被用来处理二维数组。在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)获取第一行第二个元素的值。

  4. 链表:链表是一个常见的数据结构,使用指针的指针可以在链表的添加、删除等操作中起到重要作用。

    #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。函数调用结束后,充当函数返回值。

传入传出参数:

  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端查看)

全部评论

相关推荐

11-03 14:38
重庆大学 Java
AAA求offer教程:我手都抬起来了又揣裤兜了
点赞 评论 收藏
分享
评论
点赞
3
分享
牛客网
牛客企业服务