C语言指针小结

2019-08-04  本文已影响0人  凌云struggle

前言:指针的学习

   在c语言的学习过程中,指针的学习无疑是其中的一道难关,相对来说比较复杂,但是只要从地址和内存管理两方面理解指针,你也许就会发现指针并没有想象中那么难,希望下面的内容能解决你在学习指针中的困扰。

一、指针介绍

1. 为什么要用指针

解决跨区域(不同的作用域 不同代码块)之间的数据交互

例如通过函数来改变数值:

//通过指针传给函数地址 来改变变量的值
//如果使用形式参数则达不到这样的效果
void test(int *a){
    *a++;
}

int main(int argc, const char * argv[]) {
    int a = 10;
    int *pa = &a;
    test(pa);
    printf("%d\n",a);

return 0;
}

2. 指针的表现形式

1.声明/定义变量的时候 表示一个指针变量

        float b = 20;
        int c = 10;
        int *a;   定义一个指针变量 指向的内存空间只能放整数
        注意:定义指针变量的时候画一定要给初值  不确定就给NULL
        int *a = b;不行,指针变量只能存地址 不能存具体值
        int *a = &b;不行,整型指针只能存整形数据的地址

         int *a = &c;正确
         float *d = NULL;NULL指向内存的起始地址 0x00
  1. 除了定义指针变量之外 都是访问某个 地址的值
     int *temp = &c;  //访问指针变量
     *temp = 21;访问temp地址里面的数据 赋值为21

取某个变量的地址,如最熟悉的scanf函数

3. 指针的占用内存

所有的指针类型都占8个字节(64位)

二、指针的运用

1. 函数指针

int test(int a){
    return 0;
}

int main(int argc, const char * argv[]) {
    
    int(*pFunc)(int)  = test;

return 0;
}

2. 数组与指针的关系

  数组名并不是一个变量,没有分配内存空间 例如int a = 10;而指针变量是有内存空间的

int score[5] = {1,2,3,4,5};
    printf("%p\n",score);
    printf("%p\n",&score);
    
    for (int i = 0; i < 5; i++) {
        printf("%d ",*(score + i));
        //加i个元素   score+ i = 0x7ffeefbff510 + i*4
    }
    printf("\n");
    
    printf("%p\n",score);  //0x7ffeefbff510
    printf("%p\n",score+1);  //0x7ffeefbff514
    printf("%d\n",*(score+1)); //2
    printf("%d\n",*score+1); //2
    
    printf("%d\n",(*score)++);  //1
    printf("%d\n",score[0]);    //2
    printf("%d\n",++*score);  //3

*(score + i)表示加I个元素,而不是加i个字节

例如整型数据:

score+ i = 0x7ffeefbff510 + i**sizeof(int)
定义类型 数组 指针变量
区别 系统会分配内存空间 可以存值 只为变量本身分配8个字节内存空间 无法存值
struct Person{
        char name[10];   //字符有对齐 与最近的对齐
        char *address;
        int age;
    };

    
    //定义结构体struct Person变量 变量名xw
    int i;
    struct Person xw;
   // xw.name = "小王";   //数组一旦定义 地址不能改变
                     //不能直接给数组赋值
    
    xw.name[0] = 'x';   //系统为这个变量分配内存了
    xw.name[1] = 'w';
    
   xw.address = "西南大学";    //常量字符串地址是由系统分配的
    
    //先为address分配内存
    xw.address = malloc(2 * sizeof(char));
    xw.address[0] = 's';      //字符指针赋值
    xw.address[1] = 'n';
    
    
    xw.age = 30;
    
//结构体赋值用大括号{}
   int i2 = 10;
   struct Person zs = {"张三",20};
    
    printf("name:%s\n",xw.name);
    printf("address:%s\n",xw.address);

链接1    链接2  链接3

3. 给指针指向的区域赋值

  • 指针变量已经指向某块区域
int a = 10;
int *pA = &a;  //指向变量a的内存地址
 *pA = 30;
  • 指针指向一个数组
    int num[10] = {};
    int *pNum = num;  //指向数组num的首地址
    
    *(pNum + 0) = 20;
    pNum[0] = 20;
  • 动态分配内存 malloc realloc free

 注意:
        1. 自己分配的内存空间 必须自己释放
        2. 普通变量的内存是系统分配 所以系统自己释放
        3. 常量字符串地址是由系统分配的

char *pName = malloc(3 * sizeof(char));
    //判断分配是否成功
    if (pName == NULL) {
        //分配失败
        exit(EXIT_FAILURE);
    }

    pName[0] = 'j';
    pName[1] = 'a';
    pName[2] = 'c';
    
    printf("%s\n",pName);
    
    //当之前分配的内存空间不够了 就需要在之前的基础上重新分配
    //realloc 必须是之前使用melloc分配过的
    //如果是系统分配的内存 不能使用realloc
    //用完了就要自己释放内存
    
    pName = realloc(pName, 4*sizeof(char));
    pName[3] = 'k';
    
    
//手动释放内存
    free(pName);

4. 单链表

//定义一个学生的结构体节点
typedef struct Node{
    char name[10];
    int ID;
    float score;
    
    struct Node *next;     //32个字节
} Student;

//初始化一个头结点
void initHeader(Student **pHeader){
    //动态分配内存
    Student *pTemp = malloc(1 * sizeof(Student));
    
    //初始化
    pTemp->next = NULL;
    //改变外部的值
    *pHeader = pTemp;
    
    
}

三、心得体会

  指针这块的知识理解程度还是不够深,要靠平时更多的积累来加深,通过更多的demo练手,灵活运用指针,使代码更加简洁。

上一篇下一篇

猜你喜欢

热点阅读