C语言指针

指针:

  • 指针的概念:
    指针就是地址。

  • 内存:
    内存的每一字节都分配了一个编号,从0x00 00 00 00 开始到 0x ff ff ff ff
    这个编号咱们称之为内存的地址。

  • 指针变量:
    存放地址编号的变量被称为指针变量。
    指针变量的分类:
    按类型分:

  • 一级指针

char * p ; //字符指针变量 可以保存字符变量的地址,或字符串的地址。
int * p;//整型指针变量 可以保存整型变量的地址
long int *p;
float *p;//浮点型的指针变量,可以保存float类型变量的地址。
double *p //双浮点型的指针
多级指针:指针的指针
char **p;//可以保存char * 类型变量的地址。
int **p;
float **p;
数组指针:
int (*p)[4]; //定义了一个数组指针,p=p+1 一下跳一个整型数组(有四个元素)
函数指针:
int (*p)(char *,int );//定义了一个函数指针变量p ,可以保存函数的入口地址。
注意p所指向的函数,必须有一个int类型的返回值,第一个形参类型必须是char * ,第二个形参必须是int
  • 指针数组:
    指针数组,本身是一个数组。
int *p[5];//定义了一个整型的指针数组,数组有5个元素,每个元素都是 int *类型的指针变量。

int (*p[6])(char *,int );//定义了一个函数指针数组,有6个指针,分别是p[0]~p[5]
  • 指针和函数的关系:
    指针可以作为函数的返回值
    void * malloc (int size);//malloc这个函数返回的就是一个指针。

举例1:

     char * fun()
     {
          char str[]="hello world";
          return str;
     }
     int main()
     {
          char *p;
          p=fun();
          printf("p=%s\n",p);
     }
 程序的执行结果。
 打印乱码,因为str是一个局部数组,函数调用完毕后str数组就被释放了,内容就不确定了

举例2:

char * fun()
     {
          char *str="hello world";
          return str;
     }
     int main()
     {
          char *p;
          p=fun();
          printf("p=%s\n",p);
     }
 程序执行结果:打印hello world
 因为hello world在文字常量区,返回地址给p赋值,p就指向了文字常量区,文字常量区的东西
 在程序运行过程中一直存在。

举例3:

  char * fun()
   {
        static char str[]="hello world";
        return str;
   }
   int main()
   {
        char *p;
        p=fun();
        printf("p=%s\n",p);
   }

 程序执行结果:打印hello world
 因为str是静态数组,函数结束后,不释放其空间,还存在,所以可以打印str的内容。

指针可以作为函数的参数
1:传变量的地址
例1:

void fun(int *p)
{
     *p=9;
}
int main()
{
     int a=10;
     fun(&a);
     printf("a=%d\n",a);
}

程序的执行结果 a=9;
因为p指向main 函数中的a ,*p =9 其实就是给main函数中的a赋值.

例2:

void fun(int p)
{
     p=9;
}
int main()
{
     int a=10;
     fun(a);
     printf("a=%d\n",a);
}

//此程序执行的结果是 a=10;
注意a给p赋值,p的值是10 然后再fun中重新给p赋值为9 ,
p是一个局部变量,函数结束后p释放了,在fun中没有给main函数中的a赋值,所以
main函数中的a的值还是10

例3:

void fun(char *p)
{
     p="I love China!!!";
}
int main()
{
     char *str="hello world";
     fun(str);
     printf("str=%s\n",str);
}

此程序的运行结果,hello world

调用fun的时候用str给p赋值,p是局部变量,指向了hello world 在fun中
p又指向了 I love China!!!,fun结束后p被释放了,在fun中没有给str赋值。
所以str还是指向helloworld

例4:

void fun(char **p)
{
     *p="I love China!!!";
}
int main()
{
     char *str="hello world";
     fun(&str);
     printf("str=%s\n",str);
}

此程序的运行结果,I love China!!!
因为用str变量的地址给p赋值,*p等价于main函数中str 让其指向I love China!!!

总结:要想改变主调函数中变量的值,必须传变量的地址,无论它是什么类型的变量。

2:传数组的地址

指针可以保存函数的入口地址

传一维数组的地址
// 定义方法1

void fun(int p[])
{

}

// 定义方法二

void fun(int *p)
{
     p[1]=10;
     *(p+1)=10;
}

//方法一和方法二等价,形参将来都认为是 int *类型的

int main()
{
     int a[10];
     fun(a);//传数组的名字
}

传二维数组的地址
// 定义方法1

void fun(int p[][10])//行数可以不给出,但是列数一定要给出。
{

}

// 定义方法二

void fun(int (*p)[10])
{
    
}

//方法一和方法二等价,形参将来都认为是 数组指针类型的。

int main()
{
     int a[4][10];
     fun(a);//传数组的名字,数组的名字就是数组的首地址。
}

传指针数组的地址

int my_strtok(char *q,char *s,char **p)
{
     int i=0;
     p[i]=strtok(q,s);
     while(p[i]!=NULL)
     {
          i++;
          p[i]=strtok(NULL,s);
     }
     return i;
}
int main()
{
     char str[]="秀涛:15010248451:你好,在吗?";
     char *p[4];//该数组有4个元素p[0]~p[3] 每个元素是char *
     char *str1=":";
     int n;
     n=my_strtok(str,str1,p);
     for(i=0;i<3;i++)
     {
    
     }
}

动态内存申请:
动态申请的内存在堆里开辟
malloc
calloc
relloc

void * malloc (int size);
malloc会申请一块连续的size个字节的空间,并且返回首地址
申请的内存里存放的东西是未知的。

void* calloc(int count,int size);
在堆里开辟count块,每一块是size个字节,连续的存储空间,
并且会把申请的内存的每一个字节全部变成0

void *relloc(void *p,int newsize);
接着以前申请的内存(首地址是p)重新申请newsize个字节。
注意p必须指向堆,不能是文字常量区,也不能是静态全局区,也不能是栈区

char *p;
p=(char *)malloc(100);//申请100个字节,让p去指向
如果想追加申请50个字节。
不能再次malloc,因为两次malloc出来的内存,可能不连续
p=(char *)relloc(p,150);//在原先内存的后边追加申请50个字节的空间
如果100字节后边不够50个字节了
重新找一个150个字节的地方,申请150个字节,
将原先100个字节的内容拷贝过来。释放原先的100个字节,返回新内存的首地址。

如果想重新申请50个字节

p=(char *)relloc(p,50);//relloc会将原先100个字节的后边的50个字节释放掉。

释放:
free§;
注意:释放的内存就不能再用了,并且同一块内存,不能释放多次。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值