C语言:指针

1、指针简单介绍

#include<stdio.h>
int main(void){
    int * p; // p是变量的名字, int * 表示p变量存放的是int类型的地址(指针变量)
    /*
        int * p 应该理解为 p 是变量名,p变量数据类型是 int * 类型,实际即使存放的是int变量地址的类型
     指针就是一个操作受限的非负整数 (只能相减,只能是两个指针变量指向的是同一块连续空间的不同存储单元才可以相减)
*/ int i = 3; int j = 0; /* 1、p 保存了i的地址,因此 p指向了 2、p 不是 i,i 也不是 p, 修改 p 的值不会修改 i 的值 3、如果一个指针变量指向某个普通变量,则 *指针变量 就等同于 普通变量 *p 等同于 i (在所有出现 *p 可以换成 i 在所有出现 i 的地方都可以换成 *p) */ p = &i; j = *p; printf("i = %d,j = %d",i,j);//i = 3,j = 3 }

2、指针的重要性

  • 表示一些的复杂的数据结构

  • 快速的传递数据

  • 使函数返回一个以上的值

  • 能直接访问硬件

  • 能够方便的处理字符串

  • 理解面向对象语言中引用的基础

  • 减少内存消耗

  • 执行速度快

  • 无论是什么指针变量,永远只占4个字节(只存储所指向变量的首地址)

NULL本质也是零,但不是数字零,而是表示内存单元的编号0
计算机规定,以零为编号的存储单元的内容不可读,不可写,一般用做中断异常程序的首地址

3、指针的分类

3.1 基本类型指针

    int * p; // p是变量的名字, int * 表示p变量存放的是int类型的地址(指针变量)    int i = 3;
    int j = 0; 
    p = &i; 
    j = *p;
    printf("i = %d,j = %d",i,j);//i = 3,j = 3
#include<stdio.h>
int main(void){
    int * p; 
    int i = 5;
    int * q;
    /*
        此时 p 中存储一个垃圾值,程序无法读取 *p的内容
        因为 *p所代表的内存单元的控制权限没有分配怕给本程序 
    */
    *p = i; //error
    p = &i;
    *q = p;//error 语法错误 等同于 int变量 = 指针变量
     
    printf("%d",*p);//i = 3,j = 3
} 

3.2 指针和数组

指针和一维数组

  一维数组名是一个指针常量(不能赋予其他值)。

  它存放的是一维数组第一个元素的地址。

下标和指针的关系

  如果p是个指针变量,则

  p[i] 永远等价于 *(p + i)

确定一个一维数组需要两个参数

  •   第一个元素地址
  •   数组的长度

3.3 动态分配内存

#include<stdio.h>
#include<malloc.h>
int main(void){
    int i = 5;  // 分配了4个字节 静态分配
    // malloc 是 memory 内存 和 allocate 分配 的缩写 
    /*
        1. 要使用malloc函数 ,需加  malloc.h 头文件
        2. malloc 函数只有一个形参,并且形参是个整形
        3。 4表示请求系统为本程序分配 4 个字节
        4. malloc 函数只能返回第一个字节的地址
        5. p 本身占 4 个字节,p所指向的内存也占 4 个字节 
        6. p本身所占的内存是静态分配的,p所指向的内存是动态分配的 
    */
    int * p = (int *)malloc(4); 
    
    free(p);//表示把当前p所指向的内存给释放掉 
} 

3.4 多级指针

int i = 10;
int * p = &i;
int ** q = &p;
int *** r = &q; 

 

#include<stdio.h>
#include<malloc.h>


void f(int ** q){ // q是个指针变量,无论 q 是什么类型的指针变量,都只占4个字节
int i = 5; // 静态变量
// *q 等价于 p,q 和 **q都不等价于p
*q = &i;
}

 

int main(void){
int * p;

f(&p);
printf("%d\n",*p); // error 本语句语法无问题,但逻辑上有问题。
/*
*p 保存的是 i 的值,但 i 在函数返回后就被系统回收,此时强行访问系统未分配的内存地址
*/
return 0;
}
#include<stdio.h>
#include<malloc.h>


void f(int ** q){ 

    *q = (int*)malloc(sizeof(int)); // 动态分配内存
    
    // q = 5; //error
    // *q = 5; //p = 5 error
    **q = 5; //*p = 5
}

 

int main(void){
    int * p;
    
    f(&p);
    printf("%d\n",*p);
    free(p);
    return 0;
}

4、结构体

#include<stdio.h>
#include<malloc.h>


struct Student{
    int age;
    float score;
    char sex;
};

int main(){
    struct Student st = {80,66.6,'p'}; // 初始化 定义的同时赋值 
    struct Student * pst = &st; // &st不能改成 st
    // 取成员变量
    // 1.结构体变量.成员名
    st.age = 10;
    // 2.指针变量名->成员名 
    pst->sex = 'g'; // 等价于 (*pst).sex 等价于 st.sex 
    return 0;
}
#include<stdio.h>
#include<string.h>

struct Student{
    int age;
    float score;
    char name[100];
};

// 通过函数向结构体变量赋值 ,必须发送 st 的地址 
void inputStruct(struct Student * pstu){
    (*pstu).age = 20;
    (*pstu).score = 44.5;
    strcpy((*pstu).name,"张三");
} 

// 对结构体变量输出,可以发送地址,也可以直接发送值。
// 发送地址会有不安全的隐患,但占用内存小,速度快 
// 因此在Java 中class 或者 c++中的const 等其他语言中使用对应关键字解决 
 void outputStruct(struct Student *pst){
    printf("%d,%.2f,%s",pst->age,pst->score,pst->name);
} 
int main(){
    struct Student st = {80,66.6,'p'}; // 初始化 定义的同时赋值 
    inputStruct(&st);
    outputStruct(&st);
    return 0;
}
posted @ 2023-06-18 16:10  颜欢兮  阅读(26)  评论(0)    收藏  举报