c语言之指针

指针

  • 表示一些复杂的数据结构
  • 快速的传递数据
  • 使函数返回一个以上的值
  • 能够直接访问硬件
  • 能够方便的处理字符串
  • 是理解面向对象语言中引用的基础

指针就是地址,地址就是指针

地址就是内存单元的编号,  内存地址用十六进制表示

指针变量是存放地址的变量

指针和指针变量是两个不同的概念

但是要注意:通常我们叙述时会把指针变量简称为指针,实际它们含义并不一样

总结:指针是C语言的灵魂

#include <stdio.h>

int main(void) 
{
    int i = 5;
    int * p;
    int * q;

    p = &i;
    //*q = p; //语法编译会出错,int *类型不能赋值给int类型
    //*q = *p; //error ,q没有赋值
    p = q; //q是垃圾值,q赋值给p,p也编程垃圾值
    printf("%d", *q); //13行
    /*
        q的空间是属于本程序的,所有本程序可以读写q的内容
        但是如果q内部是垃圾值,则本程序不能读写*q的内容
        因为*q所代表的内存单元的控制权限并没有分配给本程序    
        所以本程序运行到13行就会立即报错
    */

    return 0;
}

指针的定义

地址

  内存单元的编号

  从0开始的非负整数

  范围:

指针

  指针就是地址,地址就是指针

  指针变量就是存放内存单元编号的变量,或者说指针变量就是存放内存地址的变量

  指针的本质就是一个操作受限的非负整数

 1 #include <stdio.h>
 2 
 3 int main(void) 
 4 {
 5     int * p; //p是变量的名字,int * 表示p变量存放的是int类型变量的地址
 6             //int * p;不表示定义了一个名字叫做*p的变量
 7             //int * p;应该这样理解:p是变量名,p变量的数据类型是int *类型
 8             //            所谓的int *类型实际  就是存放int变量地址的类型
 9     int i=3;
10     int j;
11 
12     //p = i;//error,因为类型不一致,p只能存放int类型变量的地址,不能存放int类型变量的值
13     //p = 55;//error ,原因同上
14 
15     p = &i;
16     /*
17         1.p保存了i的地址,因此p指向i
18         2.p不是i,i也不是p,更准确的说:修改p的值不影响i的值,修改i的值也不影响p的值
19         3.如果一个指针变量指向了某个普通变量,则
20             *指针变量 就完全等价于 普通变量
21             例子:
22                 如果p是个指针变量,并且p存放了普通变量i的地址
23                 则p指向了普通变量i
24                 *p 就完全等同于 i
25                 * 或者说:在所有出现*p的地方都可以替换成i
26                             在所有出现i的地方都可以替换成*p
27 
28                 *p 就是以p的内容为地址的变量
29     */
30 
31     j = *p; //等价于 j = i;
32     printf("i=%d,j=%d,*p=%d\n",i,j,*p);
33     return 0;
34 
35 }

指针的分类

基本类型指针

# include <stdio.h>

void huhuan_1(int, int);
void huhuan_2(int *, int *);
void huhuan_3(int *, int *);


int main(void) 
{
    int a = 3;
    int b = 5;
    
    huhuan_3(&a, &b);

    printf("a = %d,b = %d\n", a, b);

    return 0;
}

//不能完成互换功能
void huhuan(int p, int q) 
{
    int t = 0;

     t = p;
     p = q;
     q = t;
}

//不能完成互换功能
void huhuan_2(int* p, int* q)
{
    int* t; //如果要互换p和q的值,则t必须是int *,不能是int,否则会出错
    t = p;
    p = q;
    q = t;
}

void huhuan_3(int* p, int* q)
{
    int t; //如果要互换*p和*q的值,则t必须定义成int,不能是int *,否则会出错
    t = *p; //p是int *.*p是int
    *p = *q;
    *q = t;
}

*的含义

  1. 乘法
  2. 定义指针变量
    • int * p;定义了一个名字叫p的变量,int *表示p只能存放int变量的地址
  3. 指针运算符
    • 该运算符放在已经定义好的指针变量的前面
    • 如果p是一个已经定义好的指针变量
    • 则*p表示 以p的内容为地址的变量

如何通过被调函数修改主调函数普通变量的值

  1. 实参必须为该普通变量的地址
  2. 形参必须为指针变量
  3. 在被调函数中通过
    1. *形参名=....的方式就可以修改主调函数相关变量的值
# include <stdio.h>

int f(int i, int j) 
{
    return 100;
}

void g(int* p, int* q)
{
    *p = 1;
    *q = 2;

}

int main(void) 
{
    int a = 3, b = 5;
    g(&a, &b);
    printf("%d %d\n", a, b);
}

指针和数组

指针和一维数组

一维数组名

#include <stdio.h>

int main(void) 
{
    int a[5]; //a是数组名 5是数组元素的个数 元素就是变量a[0]--a[4]
//    int a[3][4]; //3行4列 a[0][0]是第一个元素 啊a[i][j]第i+1行j+1列 

    printf("%#X\n", &a[0]);
    printf("%#X\n", a);
    return 0;
}
  • 一维数组名是个指针常量
  • 它存放的是一维数组第一个元素的地址
  • 它的值不能被改变
  • 一维数组名指向的是数组的第一个元素

下标和指针的关系

  如果p是个指针变量,则

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

  确定一个一维数组需要几个参数【如果一个函数要处理一个一维数组,则需要接收该数组的哪些信息】

# include <stdio.h>

//f函数可以输出任何一个一维数组的内容
void f(int * pArr,int len) 
{
    int i;
    for (int i=0;i<len;i++)
        printf("%d ", * (pArr + i));
    printf("\n");
}

int main(void) 
{
    int a[5] = { 1,2,3,4,5 };
    int b[6] = { -1,-2,-3,4,5,-6 };
    int c[100] = { 1,99,22,33 };

    f(a,5); //a是int *
    f(b, 6);
    f(c, 100);

    return 0;
}

  需要两个参数:

  • 数组第一个元素的地址
  • 数组的长度
#include <stdio.h>

/*
    一定要明白 5行的pArr[3]和12行 14行的a[3]是同一个变量
*/
void f(int* pArr, int len) 
{
    pArr[3] = 88; //5
}

int main(void)
{
    int a[6] = { 1,2,3,4,5,6 };
    
    printf("%d\n", a[3]); //4 12行
    f(a, 6);
    printf("%d\n", a[3]); //88 14行
}
#include <stdio.h>

void f(int* pArr, int len) 
{
    int i;
    for (i = 0;i < len, i++) 
    {
        printf("%d ", pArr[i]);//*(pArr+i)等价于pArr[i]也等价于b[i]也等价于*(b+i)
    }
    printf("\n");
}

int main(void) 
{
    int a[5] = { 1,2,3,4,5 };
    int b[6] = { -1,-2,-3,4,5,-6 };
    int c[100] = { 1,99,22,33 };

    f(b, 6);

    return 0;
}

指针变量的运算

指针变量不能相加 不能相乘 不能相除

#include <stdio.h>

int main(void) 
{
    int i = 5;
    int j = 10;
    int * p = &i;
    int * q = &j;
    int a[5];

    p = &a[1];
    q = &a[4];
    printf("p和q所指向的单元相隔%d个单元\n", q - p);
}

如果两个指针变量指向的是同一块连续空间中不同的存储单元,则这两个指针变量才可以相减

一个指针变量到底占几个字节

sizeof(数据类型)

功能:返回值就是该数据类型所占的字节数

例子:sizeof(int)=4 sizeof(char)=1 sizeof(double)=8

 

sizeof(变量名)

功能:返回值就是该数据类型所占的字节数

假设p指向char类型变量(1个字节)

假设q指向int类型变量(4个字节)

假设r指向double类型变量(8个字节)

p q r本身所占的字节数是否一样

总结:一个指针变量,无论它指向的变量占几个字节该指针变量本身只占四个字节

一个变量的地址使用该变量首字节的地址来表示

指针和二维数组

指针和函数

指针和结构体

多级指针

posted @ 2024-05-06 15:55  万溪汇海  阅读(1)  评论(0编辑  收藏  举报