C语言基础-指针

1.指针是什么?

指针是内存中一个最小单元的编号,也就是地址

平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量

总结:指针就是地址,口语中说的指针通常指的是指针变量

// 指针是什么?
// 1.指针是内存中一个最小单元的编号,也就是地址
// 2.平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量
// 总结:指针就是地址,口语中说的指针通常指的是指针变量
int main()
{
    int a = 100;  //在内存中开辟一块空间
    int * pa = &a;  //pa是专门来存放地址(指针)的,pa在这里就被称为指针变量
    //这里我们对变量a,取出它的地址,可以使用&操作符
    //a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量中,p就是一个指针变量
    // int arr[10];
    // printf("%p\n",&a);
    printf("%p\n",pa);


    return 0;

}

2.指针和指针类型

int* 的指针解引用访问4个字节

char* 的指针解引用访问1个字节

结论:指针类型可以决定指针解引用的时候访问多少个字节(指针的权限)

int* 4个字节  char* 1个字节  short* 2个字节  float* 4个字节   double* 8个字节

//指针类型的意义
int main()
{
    int a = 0x11223344; //0x开头是16进制数字
    
    //int * pa = &a;    
    char * pa = &a;
    // int* 的指针解引用访问4个字节
    // char* 的指针解引用访问1个字节
    // 结论:指针类型可以决定指针解引用的时候访问多少个字节(指针的权限)
    *pa = 0;

    return 0;
} 
//type * p     *说明p是指针变量
//1. p指向的对象的类型
//2. p解引用的时候访问的对象大小是sizeof(type)

int main()
{
    int a = 0x11223344; //0x开头是16进制数字
    
    int* pa = &a;    
    char* pc = &a;
    printf("%p\n",pa); //0x16d207388
    printf("%p\n",pc);//0x16d207388

    //int * 增加4个字节,char * 增加1个字节
    printf("%p\n",pa+1); //0x16d20738c
    printf("%p\n",pc+1);//0x16d207389
    //指针类型决定指针+1/-1操作时的步长
    //整形指针+1跳过4个字节
    //字符指针+1跳过1个字节

    return 0;
}

3.野指针

//野指针
// int main()
// {
//     int a = 10;
//     int* pa = &a;
//     *pa = 20;
//     printf("%d\n",a);

//     return 0;
// }


//p是野指针   野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)
// int main()
// {
//     int* p; //局部变量不初始化的时候,内容是随机值
//     *p = 20;
//     printf("%d\n",*p);

//     return 0;
// }

//指针越界访问
// int main()
// {
//     int arr[10] = {0};
//     int* p = arr;
//     int i = 0;
//     for(i = 0; i<= 11;i++)
//     {
//         //当指针指向的范围超出数组arr的范围时,p就是野指针
//         *(p++) = i;
//     }
//     return 0;
// }

//指针释放
int* test()
{
    int a = 110;
    return &a;
}
int main()
{
    int* p = test();
    printf("%d\n",*p);


    return 0;
}

如何规避野指针:

1指针初始化

2小心指针越界

3指针指向的空间释放,及时置NULL

4避免返回局部变量的地址

5指针使用之前检查有效性

// 如何规避野指针:
// 1指针初始化
int main()
{
    int a = 0;
    int* p = &a;

    int* ptr = NULL; //告诉你ptr是一个空指针,没有指向任何有效的空间,这个指针不能直接使用
    int* ptr2; //野指针

    if (ptr != NULL)
    {
        //使用
    }
    

    return 0;
}
// 2小心指针越界
// 3指针指向的空间释放,及时置NULL
// 4避免返回局部变量的地址
// 5指针使用之前检查有效性

4.指针运算

指针+ - 整数

//指针运算
// int main()
// {
//     int arr[10] = {0};
//     //不使用下标访问数组
//     int* p = &arr[0];
//     int i = 0;
//     int sz = sizeof(arr)/sizeof(arr[0]);
//     for (int i = 0; i < sz; i++)
//     {
//         *p = i;
//         p++; // p = p+1
//     }
//     p = arr;

//     for (i = 0; i < sz; i++)
//     {
//         printf("%d ",*(p+i)); // p+i
//     }

//     // for (i = 0; i < 10; i++)
//     // {
//     //     printf("%d",arr[i]);
//     // }

//     return 0;
// }

//int arr[10];
//int* p = arr;
//*(p+i) ==  arr[i]
//*(arr+i) == arr[i]
//数组名是首元素的地址 -- 指针
//arr[i] == *(arr+i) == *(i+arr) == i[arr]

int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    int i = 0;
    int *p = arr;
    for(i = 0;i < 10; i++)
    {
        printf("%d ",i[arr]); //[]操作符
        printf("%d ",*(p+i)); //[]操作符
    }

    //arr[i] --> i[arr]


    return 0;

}

// int my_strlen(char* s)
// {
//     int count = 0;
//     while (*s != '\0')
//     {
//         count++;
//         s++;
//     }

//     return count;
// }

//递归实现
// int my_strlen(char* s)
// {
//     if (*s == '\0')
//     {
//         return 0;
//     } else
//     {
//         return 1 + my_strlen(s + 1);
//     }
//    return 0;
// }
int my_strlen(char* s)
{
    char* start = s;
    while (*s != '\0')  //(*s)
    {
        s++;
    }
    // while (*s++); //err
    //while (*s++);   return s -start-1; //true

    return s -start;
    
}

int main()
{
    char arr[] = "abcdef"; // a b c d e f \0
    int len = my_strlen(arr);
    printf("%d\n",len);

    return 0;
}

5.指针和数组

//指针和数组之间是什么关系呢?
//指针变量就是指针变量,不是数组,指针变量的大小是4/8个字节,专门是用来存放地址的
//数组就是数组,不是指针,数组一块连续的空间,可以存放一个或者多个类型相同的数据
//指针和数组之间的关系:数组中,数组名其实是数组首元素的地址,数组名 == 地址 == 指针
//当我们知道数组首元素的地址的时候,因为数组又是连续存放的,使用通过指针就可以遍历访问数组,数组是可以通过指针访问的
// int main()
// {
//     int arr[10] = {1,2,3,4,5,6,7,8,9,10};
//     int i = 0;
//     int sz = sizeof(arr) / sizeof(arr[0]);
//     int* p = arr;
//     for(i = 0; i < sz; i++)
//     {
//         printf("%p == %p\n",p+i,&arr[i]);
//     }

//     return 0;
// }

// int main()
// {
//     int a = 10;
//     int* p = &a;//p是一级指针变量,指针变量也是变量,变量是在内存中开辟空间的
//     int** pp = &p; //pp就是二级指针,二级指针变量就是用来存放一级指针变量的地址
//     *(*pp) = 100;
//     *p = 10;
//     int** * ppp = &pp;
//     //int* 是在说明pp指向的是int*类型的变量
//     printf("%d\n",a);
//     printf("%p\n",&a);
//     printf("%p\n",&p);
//     printf("%p\n",pp);

//     return 0;
// }

6.二级指针

// int main()
// {
//     int a = 10;
//     int* p = &a;//p是一级指针变量,指针变量也是变量,变量是在内存中开辟空间的
//     int** pp = &p; //pp就是二级指针,二级指针变量就是用来存放一级指针变量的地址
//     *(*pp) = 100;
//     *p = 10;
//     int** * ppp = &pp;
//     //int* 是在说明pp指向的是int*类型的变量
//     printf("%d\n",a);
//     printf("%p\n",&a);
//     printf("%p\n",&p);
//     printf("%p\n",pp);

//     return 0;
// }

int main()
{
    char arr1[] = "abcdef";
    char arr2[] = "hello world";
    char arr3[] = "xiaofan";

    char* parr[] = {arr1,arr2,arr3};
    int i = 0;
    int sz = sizeof(parr)/sizeof(parr[0]);
    

    char** p = parr;
    for (i = 0;i<sz;i++)
    {
        //printf("%s\n",parr[i]);
        printf("%s\n",*(p+i));
    }
    //**p = '1111';
    //printf("%s\n",parr[0]);


    return 0;
}

7.指针数组

//指针数组
//指针数组是指针还是数组     是数组,是存放指针的数组  数组我们已经知道整形数组,字符数组
//整型数组 -存放整型的数组    字符数组 - 存放字符的数组    指针数组-存放指针(地址)的数组

int main()
{
    // char arr[] = "abcdef";
    // printf("%s\n",arr);
    int arr1[] = {1,2,3,4,5};
    int arr2[] = {2,3,4,5,6};
    int arr3[] = {3,4,5,6,7};
    //指针数组
    int* parr[] = {arr1, arr2, arr3};
    int i = 0;
    for(i = 0;i<3;i++)
    {
        int j = 0;
        for(j = 0;j <5;j++)
        {
            //printf("%d ",parr[i+j]);//err
            printf("%d ",*(parr[i]) + j);
            // printf("%d ",parr[i][j]);
        }
        printf("\n");
    }
     
    return 0;
}

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值