24/06/05(1206)指针

指针类型的理解.

        1.内存中房间号(地址)是什么(指针变量中存的数据)

        2.对应的房间号多大.(指针的类型之中)

        char* 和 int* 两种不同的类型,不能互相赋值.

一种特殊的类型,void*(不是空指针):只考虑指针的地址是啥,不考虑这块内存的大小.

void* 不能进行解引用,如果有些函数需要同时处理多种类型的指针的时候,使用 void* 就比较合适.

例如 memste (传数组把某片连续空间设成某个值)参数就是 void*

指针运算

指针运算是一种"弊大于利"的操作.

指针运算很容易产生"野指针".

指针 +- 整数 ; 指针 - 指针 ; 指针的关系运算.

指针 + 整数 VS 整数 + 整数

#include <stdio.h>
#include <stdlib.h>

int main(){

    char* p = (char*)0x100;
    printf("%p\n",p + 1);
    system("pause");
    return 0;
}

#include <stdio.h>
#include <stdlib.h>

int main(){

    int* p = (int*)0x100;
    printf("%p\n",p + 1);
    system("pause");
    return 0;
}

#include <stdio.h>
#include <stdlib.h>

int main(){

    double* p = (double*)0x100;
    printf("%p\n",p + 1);
    system("pause");
    return 0;
}

指针 + 1 相当于地址向后跳过一个元素.

指针 - 1 相当于地址向前跳过一个元素.

#include <stdio.h>
#include <stdlib.h>

int main(){

    int arr[4] = { 1, 2, 3, 4 };
    int* p = &arr[0];
    printf("%p\n",arr); 可能会疑惑,数组arr可以直接用%p打印吗?

又要提到那个惊天bug!

        1.数组在作为函数参数的时候会隐式转成指针

        2.数组名直接printf打印也会隐式转成指针

        3.数组名参与算术运算也会隐式转成指针


    printf("%p\n",p);
    printf("%p\n",p + 1);
    system("pause");
    return 0;
}

#include <stdio.h>
#include <stdlib.h>

int main(){

    int arr[4] = { 1, 2, 3, 4 };
    int* p = &arr[0];
    printf("%d\n",arr[1]);
    printf("%d\n",*(p + 1)); //这是解引用
    printf("%d\n",p[1]);      //p是一个指针,它可以[]取下标
    system("pause");
    return 0;
}

*(p + 1) 和 p[1] 是等价的;可以理解成p[1] 是 *(p + 1)简化写法.但是这样的语法设定相当糟糕.

数组很多时候就隐式转成指针了.指针有时候还能像数组一样来使用(方括号取下标操作)

这俩概念相似,一定要做好区分.

数组取下标能不能填负数?不能

指针取下标能不能填负数?可以(只要它运算之后是有效内存)

#include <stdio.h>
#include <stdlib.h>

int main(){

    int arr[4] = { 1, 2, 3, 4 };
    int* p = &arr[1];
    printf("%d\n",*(p - 1));
    printf("%d\n",p[-1]);
    system("pause");
    return 0;
}

指针 - 指针(只能减不能加嗷)

#include <stdio.h>
#include <stdlib.h>

int main(){

    int arr[4] = { 1, 2, 3, 4 };
    int* p1 = &arr[0];
    int* p2 = &arr[2];
    int ret = p2 - p1;
    printf("%p %p\n", p1, p2);
    printf("ret = %d\n",ret);
    
    system("pause");
    return 0;
}

指针相减本质上就是在算两个指针之间隔了几个元素(和指针类型相关).

指针相减其实算是指针 +- 整数的逆运算.

p2 - p1 => 2;p1 + 2 => p2

指针相减大部分情况下虽然语法允许,但是是没有意义的.

指针相减要想有意义,必须满足两个条件:

        1.两个指针的类型相同.

        2.两个指针必须要指向同一个连续的内存空间.

因为 void* 未知大小,所以不能进行+-整数的运算,也不能进行指针相减.

指针的关系运算

针对比较相等,这个还好. 规则就是比较两个指针中存的地址是不是一样的.

==

!=

针对比较大小,这个一般也是没有意义的.比较地址数值的大小.

一般是不需要用的.如果非要用的话,也要保证两个前提.

1.两个指针类型相同

2.两个指针指向同一个连续的内存空间(数组,malloc)

<

<=

>

>=

比较两个字符串可以使用 "=="来直接比较吗?

#include <stdio.h>
#include <stdlib.h>

int main(){

    char str1[] = "hehe";
    char str2[] = "hehe";
    printf("%p %p\n",str1,str2);
    if (str1 == str2){
        printf("1\n");
    }
    else{
        printf("2\n");
    }
    system("pause");
    return 0;
}

我们发现它的输出结果并不相等.因为它是两个数组的地址在进行比较.

如果想要比较两个字符串的内容相等与否需要引入string.h头文件中的cmp.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){

    char str1[] = "hehe";
    char str2[] = "hehe";
    printf("%p %p\n",str1,str2);
    //str => string ; cmp => compare
    if (strcmp(str1,str2) == 0){
        printf("相等\n");
    }
    else{
        printf("不相等\n");
    }
    system("pause");
    return 0;
}

C语言中,比较两个字符串,有两种方式:

        1. == 比较字符串的身份/地址(是不是同一个字符串变量)

        2.strcmp 比较字符串的内容(字符串里面每个字符是不是依次相同)

strcmp 除了能比较字符串相等之外,还能比较字符串的大小.

字符串大小的比较规则:先看第一个字符的ASCII值的大小.如果能分出大小,结果就确定了,如果第一个字符相同,再依次比较下一个字符的ASCII.字典序

strcmp(str1,str2)

如果str1 小于 str2 返回一个 < 0 的整数(不是-1)

如果str1 大于 str2 返回一个 > 0 的整数(不是+1)

换一种写法:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){

    char* str1 = "hehe";
    char* str2 = "hehe";

    printf("%p %p\n",str1,str2);
  
    if (str1 == str2){
        printf("相等\n");
    }
    else{
        printf("不相等\n");
    }
    system("pause");
    return 0;
}

结果会怎么样?

虽然这样比较的依然是字符串的地址,但这两个共用同一个创建的字符串常量.

二级指针

二维数组:本质上也是一个二维数组,只不过里面的元素也是一个一维数组.

二级指针:本质上也是一个一级指针,只不过这个指针指向的内容还是一个一级指针.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int* IntPtr;

int main(){

    int num = 10;
    IntPtr p = &num;
    //二级指针
    IntPtr* pp = &p;
    //*pp和p是等价的
    //*p和num是等价的
    //**pp就和num是等价的
    printf("%d\n",**pp);
    system("pause");
    return 0;
}

指针数组

指针数组:是一个数组,数组中的每一个元素是一个指针.

数组指针:是一个指针

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(){
    //指针数组
    int* arr[4] = { 0 };

    //数组指针
    int(*arr)[4] = NULL;

    //数组的类型如何理解
    //变量名叫 a,a 的类型叫做 int[4]
    //b 的类型 int[5]
    //a 的类型和 b 的是否相同? 不相同
    int a[4];
    int b[5];

    system("pause");
    return 0;
}

指针数组非常有用.以后会经常用到.数组指针没什么用,用处就是用来做指针数组的区分.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(){
    int arr[4] = { 0, 1, 2, 3 };
    int(*p)[4] = &arr;
    //int*
    printf("%p\n",&arr[0]);
    //int*
    printf("%p\n", arr);
    //int(*arr)[4]
    printf("%p\n", &arr);

    system("pause");
    return 0;
}

const 和指针搭配的时候,有说法.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(){
    int num = 10;
    int num2 = 20;
    const int* p = &num;
    
    //第一种操作,根据地址修改对应的变量
    //*p = 100;
    //第二种操作,修改指针的指向
    //p = &num2;

    system("pause");
    return 0;
}

const int* p 限制根据指针修改对应的内存

int const* p 限制根据指针修改对应的内存

int* const p 限制修改指针的指向

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值