C语言之指针的笔记

11.22 今天的内容有些难哦

img

img


取值运算符:*

取址运算符:&

占位符:%p

12.2 指针运算

12.2.1 指针加减运算
12.2.2 指针自增自减

指针加减指的是指针所指向的内存地址的移动,指针加1,就是移动指针所指向类型的长度,比如int型,就移动4个字节。

12.2.3 同类型指针相减

同类型指针相减的结果是ptrdiff_t类型的数据,ptrdiff_t类型是一个带符号的整数,格式占位符是%td。

不同类型的指针也是可以相减的,但是不同类型的指针相减没有什么意义,而且编译虽然不会报错,但是会有警告,不建议使用不同类型的指针相减。

12.2.4 指针的比较运算

指针之间可以比较运算,==,<,<=,>,>=,比较的是指向各内存地址的大小,返回值是int类型的整数0(false)或1(true)

12.3 指针和数组

12.3.1 数组名

数组名可以看作是一个常量,他的指向和内容是不可更改的,它指向的是数组的第一个元素,但是不能自增也不能自减,他的指向也不能修改,而且使用sizeof运算符,数组名会得到整个数组的大小,指针得到的是本身的大小。

指针本身的大小与编译器根据该cpu的寻址位数决定的,32位的电脑指针的大小是4字节,64位的电脑指针大小是8字节。

指针和数组可以混着用,不必掌握。

#include<stdio.h>

int main(){
    int nums[5] = {10,20,30,40,50};
    int *ptr = &nums[0];

    //数组名可以认为是一个指针,指向了数组的第一个元素
    printf("数组名的值为:%p\n",nums);
    printf("指针ptr的值为:%p\n",ptr);

    if (nums == ptr)
    {
        printf("数组名和指向数组首元素的指针的值是一样的!\n");
    }

    printf("nums[0] = %d\n",nums[0]);       //10
    printf("*ptr = %d\n",*ptr);             //10

    printf("nums[1] = %d\n",nums[1]);       //20
    printf("*(ptr+1) = %d\n",*(ptr+1));     //20

    printf("%d\n",ptr[1]);   //20
    printf("%d\n",*(nums+1));   //20

    //数组名和指针不同
    //数组名类似于指针常量,而普通的指针是变量

    printf("指针ptr的大小:%zu\n",sizeof(ptr));
    return 0;
}
12.3.2 指针数组

他是一个数组,每个元素都是指针

语法规则:

数据类型 *指针数组名[长度];
12.3.3 数组指针

他是一个指针,指向一个数组,应用在二维数组,一个指针指向一个数组,指针加1将会指向下一个数组。

应用不是很多。

语法规则:

数据类型 (*数组指针名)[长度];

数组指针和数组名虽然输出的内容相同,但是含义不同,数组指针指向的是一整个数组的地址,数组名指向的是元素的首地址。

数组名是不可变的,但是数组指针是可以改变的,它可以指向不同的数组。

数组名不需要初始化,它会自动获取到数组的首地址作为数组名,但是数组指针就需要具体的初始化,说明数组的指向。

数组名

#include<stdio.h>

int main(){

    int arr[5] = {10,20,30,40,50};
    //定义一个数组指针
    int (*arr_ptr)[5] = &arr;


    //数组指针的值
    printf("数组指针arr_ptr的值为:%p\n",arr_ptr);  //00000026abfffb50
    printf("数组名的值为:%p\n",arr);   //00000026abfffb50
    printf("&arr的值为:%p\n",&arr);        //00000026abfffb50

    //对数组指针进行加1操作
    printf("数组指针arr_ptr + 1的值为:%p\n",arr_ptr + 1);  //00000026abfffb64
    //地址00000026abfffb64与地址00000026abfffb50相差了20个字符

    printf("arr + 1的值为:%p\n",arr + 1);      //00000026abfffb54
    //地址00000026abfffb54与地址00000026abfffb50相差了4个字符


    //用数组指针遍历数组元素
    for (int i = 0; i < 5; i++)
    {
        printf("第%d个元素为:%d,地址为:%p\n",i+1,(*arr_ptr)[i],&(*arr_ptr)[i]);
    }

// 第1个元素为:10,地址为:00000026abfffb50
// 第2个元素为:20,地址为:00000026abfffb54
// 第3个元素为:30,地址为:00000026abfffb58
// 第4个元素为:40,地址为:00000026abfffb5c
// 第5个元素为:50,地址为:00000026abfffb60

    return 0;
}

arr是指向数组首元素的地址

&arr是指向整个数组的地址,他是数组指针,为指向数组的指针赋值。

12.3.4字符指针


11.24今天又是头秃的一天

img

img


字符串,可以修改的字符串,嘎嘎好用。

char *ptr = "hello tom~"

字符数组和字符指针的区别:对于字符数组修改只能一个一个修改,不能直接全部修改,但是字符指针是可变的。

12.4 指针和函数

12.4.1 传递指针给函数

函数形参内容是指针。

传递数组给函数,但是数组的本质即使传地址。

12.4.2 指针函数

一个函数他的返回值是指针。

语法规则:

返回类型 *指针函数名(参数列表)

返回值不能指向局部变量。

12.4.3 函数指针

一个函数也会占据着一段连续的空间,他与数组十分相似,把函数的首地址或者是是入口地址赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。

语法规则:

返回类型 (*函数指针名)(参数列表)
12.4.4 回调函数

函数指针作为函数的参数来使用,回调函数就是一个通过函数指针调用的函数。就是参数一个指针指向的函数。

12.4.5 多级指针

12.5 空指针

int *p = NULL;

赋值NULL,防止变成野指针。

12.6 野指针

12.6.2 野指针的成因

使用前未初始化。

指针越界访问。

指针指向已释放的空间。

12.7 指针使用一览

变量定义类型表示含义
int iint一个整型的变量
int *pint *一个整型的指针
int a[5]int[5]大小为5的整型数组
int *p[5]int *[5]数组大小为5,数组元素是整型的指针
int (*p)[5]int(*)[5]是一个指针,指向大小为5的数组
int f()int()返回值为整型的函数
int *f()int *()返回值为整型指针的函数
int (*p)()int (*)()是一个指针,指向返回值为整型的函数
int **pint **是一个二级指针
  • 18
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值