所谓指针就是创建一个变量把一个数通过存地址的方式存进去,再加以利用,比如一个最简单的
#include<stdio.h>
int main()
{
    int a = 0x11223344;//现在内存开辟一块空间
     int* p = &a;//对于变量a,去处它的地址,并将a的地址存存放在类型为指针变量,名为p的的指针变量中
    //说到这里,可能有一些和我之前一样的小白傻傻的分不清int* p与int *p的区别在哪里,前者就像我所说的一样类型为指针变量,名为p的的指针变量后者
    //后者为类型为int名为*p的变量
//    *p = ;//解引用操作,将变量*p重新赋值为20
    //printf("%d\n", *p);//
    return 0;
}
指针意义1
int main()
{
    //指针在64位平台中一个空间就占了8个字节,在32位平台就占4个字节(不管是什么类型的变量)
    int a = 0x11223344;
    printf("%p\n", &a);//009EFCB8这是a的取地址
    int* pc = &a;
    //*pc = 0;
    printf("%p\n", pc+1);////009EFCBC  在16进制中前是位是0-9,后面依次为abcdef
    //通过以上可看出指针一步能在空间走多远,就比如int类型一次在空间中可以走四个字节。这就是指针的意义
    
    return 0;
}
依次类推,char类型一次可以走一个字节的空间 double类型一次可以走8个字节空间


//指针意义2:解引用操作时有多大权限(能操作几个字符),比如char*类型指针解引用只能访问一个字节,int*类型指针解引用操作能访问4个字节  
#include <stdio.h>
int main()
{
    int arr[10] = { 0 };
    int* p = arr;
    int i = 0;
    for (i = 0; i <= 10; i++)
    {
        *(p + i) = 1;
        printf("%d  ", *p);
    }
    //结果是1 1 1 1 1 1 1 1 1 1 
    return 0;
}
当我们把i<=11时会发现一个问题,系统出错了,一定次数超过了数组的元素个数会出现野指针
所谓野指针就是指指针指向位置不知(斯基的,不正确的,无限制的)
eg int a;表示变量默认随机值,那么int* p作为局部变量也就被初始化随机值
以下情况也会出现野指针
case1;局部变量用完之后被销毁
#include <stdio.h>
int* test()
{
    int a = 10;
    return &a;//原因是当局部变量a用完之后就立即销毁,a就地释放了
}
int main()
{
    //int a = 0;
    int* p = test();
    *p = 20;//这是指针所指向的空间被释放,所以就变为了野指针
    //printf("%d %d",*p,a );//结果打出了10   0  
    printf("%p ", p);//每次打印出来的地址都不相同

    return 0;
}
如何避免野指针呢 1 将指针初始化 2 小心指针越界 3 指针指向空间被释放即设置空指针(NULL)
指针使用前检查效性 

关于指针和数组之间的
首先介绍下 int a[]={1,2,3,4,5,6},其中指的是数组首元素的地址,a[0]是数组的第一个元素&a[0]指的是数组首元素的地址,相当于一个指针变变量
数组指针相减,得到的是两数对应数组中间的元素个数(必须是同类型的)
#include <stdio.h>
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }//相当于指针减指针
    
    printf ("%d ", &arr[9] - &arr[0]);//得出结果为9
    return 0;
}

或者还可以这样子
#include <stdio.h>
int my_strlen(char* str)//因为数组arr是字符类型的所以传上来的是char类型的指针
{
    char* start = str;//用名为start的字符类型指针接受arr的地址
    char* end = str;
    while (*end != '\0')//解引用操作还可看作是char类型到int类型转换
    {
        end++;
    }
    return end - start;//相当于&arr[3]-arr[0]
}
int main()
{
    char arr[] = "bit";//这里含有字符'b'i't'\0'

    int len = my_strlen(arr);//注意传上去的是该数组的首元素地址
    printf("%d", len);//最后打印出来结果为3
    return 0;
}
c语言标准规定指向数组元素的指针与指向数组最后一个元素后面的那个内存位置相比较,但绝对不允许与指向第一个元素前的内存位置进行比较,这个后面会提及

各种数组名+1的区别
#include <stdio.h>
int main()
{
    int arr[10] = { 0 };//先初始化一波数组
    printf("%p\n", arr);
    printf("%p\n", arr+1);
    printf("%p\n", &arr[0]);
    printf("%p\n", &arr[0]+1);
    printf("%p\n",& arr);
    printf("%p\n", &arr+1);
    /*打印地址出如下结果004FF7B0
                        004FF7B4
                         004FF7B0
                         004FF7B4
                         004FF7B0
                         004FF7D8*///说明&arr打印出来的是整个数组的地址,随意加1时是整个数组十个元素加一
    return 0;
  
通过以上的叙述我们还可以发现,通过指针我们还可以访问数组
#include <stdio.h>
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int* p = arr;//在这里取首元素的地址
    int sz = sizeof(arr) / sizeof(arr[0]);//sizeof是用来计算数组大小的,此处则表示整个数组的大小除于单个数组的大小等于数组元素的个数,用sz来接受
    int i = 0;
    for (i = 0; i < sz; i++)//要注意一点,i不能等于sz;否则指针越界造成野指针!
    {
        printf("%d  %d ", arr[i], *(p+i));
        //调试之后发现两者的结果都是一样的,说明指针可以相当于数组(要说区别就在于指针能存一个数二数组顾名思义可以一存一组数)
    }
    return 0;
}
什么是二级指针,举一个栗子
int main()
{
    int a = 10;
    int* pa = &a;//int* pa就是一级指针
    int** ppa = &pa;//int** ppa就是二级指针
    //肿么理解呢,对于第76行和第75行来说,指的是整形类型的指针指向整形类型变量,对第77行来说int**里第二个*指的是一个指针,则int*则指这个指针所指向前面的int*类型
    return 0;
}
指针数组:存放着指针的数组(类比一下数组存放在整形里面(int arr[]={1,2,3};)
如何把多个整形变量存放在同一个数组里?
#include<stdio.h>
int main()
{
    int a = 10;
    int b = 20;
    int c = 300;
    int* arr[3] = { &a,&b,&&c };//指针数组,指针类型的数组
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        printf("%d  ", *(arr[i]));//10  20  300
    }
    return 0;
}int* arr[3] = { &a,&b,&c };//指针数组,指针类型的数组
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        printf("%d  ", *(arr[i]));//10  20  300
    }
    return 0;
}

 

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐