C语言知识点(二)指针(学习笔记)

强化1:指针是一种数据类型

    1)  指针变量也是一种变量,占有内存空间,用来保存内存地址
测试指针变量占有内存空间大小。
    2*p操作内存
    在指针声明时,* 号表示所声明的变量为指针
    在指针使用时,* 号表示操作指针所指向的内存空间中的值
    *p相当于通过地址(p变量的值)找到一块内存,然后操作内存
    *p放在等号的左边赋值(给内存赋值,写内存)
    *p放在等号的右边取值(从内存获取值,读内存)
    3)指针变量和它指向的内存块是两个不同的概念。
    4)指针是一种数据类型,是指它指向的内存空间的数据类型 。
int a;
int *p = &a; 
p++;
指针步长(p++),根据所致内存空间的数据类型来确定。
5 ) 当我们不断的给指针变量赋值,就是不断的改变指针变量
(和所指向内存空间没有任何关系)。指针指向谁,就把谁的地址赋值给指针。
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//不断给指针赋值就是不断改变指针的指向
int main(void)
{
    char    buf[128];
    int     i;

    char    *p2 = NULL;
    char    *p1 = NULL;

    p1 = &buf[0]; //不断的修改p1的值 相当于 不断改变指针的指向
    p1 = &buf[1];
    p1 = &buf[2];

    for (i=0; i<10; i++)
    {
        //不断改变p1本身变量
        p1 = &buf[i];
    }

    p2 = (char *)malloc(100);
    strcpy(p2, "abcdefg1212333333333311");

    for (i=0; i<10; i++)
    {
        //不断的改变p1本身变量,跟p1指向的内存块无关
        p1 = p2+i;
        printf("%c ", *p1);
    }

    return 0;
}
6 ) 不允许向NULL和未知非法地址拷贝内存。

强化2:间接赋值(*p)是指针存在的最大意义

*p间接赋值成立条件: 三大条件

条件一: 2个变量(通常一个实参,一个形参)

条件二:建立关系,实参取地址赋给形参指针 

条件三:*p形参去间接修改实参的值  
int num = 0; 
int *p = NULL;  // 条件一:两个变量          
p = &num;       // 条件二:建立关系
Num = 1;
*p = 2 ;        // 条件三:通过* 操作符, 间接的给变量内存赋值

强化3: 间接操作:1级指针

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

//使用一级指针
void  getFileLen(int *p)
{
    *p = 41;    //  p的值是file_len的地址 *p的地址间接修改file_len的值 
                     //在被调用函数里面 通过形参 去 间接的修改 实参的值...
}

int  getFileLen2()
{
    int len = 100;
    return len;
}

//不使用指针, 0级指针
void  getFileLen3(int file_len)
{
    file_len = 100;
}

//1级指针的技术推演
int main(void)
{
    int file_len = 10;   
    //条件1  定义了两个变量(实参 另外一个变量是形参p)
    int *p = NULL;

    p = &file_len;          //条件2 建立关联

    file_len = 20;         //直接修改
    *p = 30;               //条件3 p的值是file_len的地址 
                         // *就像一把钥匙 通过地址 
                    // 找到一块内存空间 间接的修改了file_len的值

    {
        *p = 40;  //  p的值是a的地址 *a的地址间接修改a的值  //条件3 *p
        printf("file_len: %d\n", file_len);
    }

    getFileLen(&file_len); //建立关联: 把实参取地址 传递给 形参
    printf("getFileLen后 file_len: %d \n", file_len);
    getFileLen3(file_len);
    printf("getFileLen3后 file_len: %d \n", file_len);
    return 0;
}   

输出结果

file_len: 40
getFileLen后 file_len: 41
getFileLen3后 file_len: 41

强化4:从1级别指针到2级指针

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


void getMem(char *p2)
{
    p2 = (char*)0x80088008;
}

void getMem2(char **p2)
{
    *p2 = (char*)0x40044004; //间接赋值  p2是p1的地址
}

int main(void)
{
    char *p1 = NULL;
    char **p2 = NULL;

    //直接修改p1的值
    p1 = (char*)0x11001100;

    //间接修改p1的值
    p2 = &p1;

    *p2 = (char*)0x10101010;    //间接赋值  p2是p1的地址

    printf("p1:%p \n", p1);

    {
        *p2 = (char*)0x20022002; //间接赋值  p2是p1的地址
        printf("p1:%p \n", p1);
    }

    getMem(p1);

    getMem2(&p1);

    printf("p1:%p \n", p1);
    system("pause");
    return 0;
}

运行结果:

p1:10101010
p1:20022002
p1:40044004

• 间接赋值的推论

用1级指针形参,去间接修改了0级指针(实参)的值。
注意这里的0级指针指的是普通类型变量
用2级指针形参,去间接修改了1级指针(实参)的值。
用3级指针形参,去间接修改了2级指针(实参)的值。
用n级指针形参,去间接修改了n-1级指针(实参)的值。

• 间接操作:应用场景 strcpy函数

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

char * Mystrcpy(char *dest,const char *src)
{
    char * temp = dest;
    if(dest==NULL||src==NULL)
    {
        return NULL;
    }

    while(*dest++ = *src++)
    {

    }
    return temp;

}

int main()
{
    char buf[]  = "hello,world";
    int len = strlen(buf);
    char *buf1 = (char*)malloc(sizeof(buf1)+1);
    if(buf1==NULL)
    {
        return -1;
    }
    Mystrcpy(buf1,buf);
    printf("buf1:%s\n",buf1);
    if(buf1!=NULL)
    {
        buf1=NULL;
        free(buf1);
    }


    system("pause");
    return 0;
}

强化5:理解指针必须和内存四区概念相结合

1) 主调函数 被调函数
a) 主调函数可把堆区、栈区、全局数据内存地址传给被调用函数
b) 被调用函数只能返回堆区、全局数据

2) 内存分配方式
a) 指针做函数参数,是有输入和输出特性的。

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

int getMem(char **myp1, int *mylen1,  char **myp2, int *mylen2)
{
    int     ret = 0;
    char    *tmp1, *tmp2;

    tmp1 = (char *)malloc(100);
    strcpy(tmp1, "1132233");

    //间接赋值 
    *mylen1 = strlen(tmp1);  //1级指针
    *myp1 = tmp1;            //2级指针的间接赋值

    tmp2 = (char *)malloc(200);
    strcpy(tmp2, "aaaaavbdddddddd");

    *mylen2 = strlen(tmp2);  //1级指针
    *myp2 = tmp2;            //2级指针的间接赋值

    return ret;
}

int  main(void)
{
    int     ret = 0;
    char    *p1 = NULL;
    int     len1 = 0;
    char    *p2 = NULL;
    int     len2 = 0;

    ret = getMem(&p1, &len1, &p2, &len2);
    if (ret != 0)
    {
        printf("func getMem() err:%d \n", ret);
        return ret;
    }

    printf("p1:%s \n", p1);
    printf("p2:%s \n", p2);

    if (p1 != NULL)
    {
        free(p1);
        p1 = NULL;
    }
    if (p2 != NULL)
    {
        free(p2);
        p2 = NULL;
    }


    return 0;
}

输出结果

p1:1132233
p2:aaaaavbdddddddd

应用指针必须和函数调用相结合(指针做函数参数)

经典语录

1)指针也是一种数据类型,指针的数据类型是指它所指向内存空间的数据类型
2)间接赋值*p是指针存在的最大意义 
3)理解指针必须和内存四区概念相结合 
4)应用指针必须和函数调用相结合(指针做函数参数)
指针是子弹,函数是枪管;子弹只有沿着枪管发射才能显示它的威力;
指针的学习重点不言而喻了吧。接口的封装和设计、模块的划分、
解决实际应用问题;它是你的工具。
5)指针指向谁就把谁的地址赋给指针 
6C/C++语言有它自己的学习特点;若java语言的学习特点是学习、应用、
上项目;那么C/C++语言的学习特点是:
学习、理解、应用、上项目。多了一个步骤。
7) 理解指针关键在内存,没有内存哪来的内存首地址,
没有内存首地址,哪来的指针。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值