c语言指针2

目录

指针与数组

小结:

指针与const

指针运算

用指针来做什么

动态内存分配

动态分配空间示例(重点)

常见问题:

没空间了怎么办?


指针与数组

传入函数的数组成了什么?

void test(int a[]);

int main() {

   int a[]={1,2,3,4,5,};

   printf("main sizeof(a)=%lu\n",sizeof(a));

   test(a);

    return 0;

}

void test(int a[])

{

    printf("test sizeof(a)=%lu\n",sizeof(a));

}

从结果发现:主函数中的sizeof得出的就是5个int的大小

而传入函数中的数组就是一个指针的大小

分别打印main中a的地址和函数中的地址

证明是同一个

 

在函数中给a[0]赋值

a[0]=1000;

在主函数中打印a[0]

printf("a[0]=%d\n",a[0]);

 

所以实际上就是个指针

甚至在声明函数时可以直接这么写

void test(int *a)

运行结果不会变

 

实际上数组变量是const指针,所以不能被赋值

也就是不能:int b[]=a;

但是可以int *q=a

他们有什么不同呢?

实际上int []b可以看做int * const b;表示b指针是个常量只能指向(代表)这个数组

被初始化出来就不能改变了

 

小结:

函数参数列表中的数组实际上是指针

sizeof(a)==size(int*)

但是可以用数组的运算符[]进行运算

 

以下四种函数原型是等价的

数组变量是特殊的指针

数组变量本身表达地址

int a[10]; int*p=a //无需用&取地址

但是数组的单元表达的是变量,需要用&取地址

a==&a[0]

[]运算符可以对数组做也可以对指针做

p[0]<==>a[0]

示例

inti=10;

int*p=&i;

printf("*p=%d\n",*p);

printf("p[0]=%d\n",p[0]);//把所指向的变量当做容量只有1的数组p[0]就是取第一个,但是不能这么写:i[0];

 

//小实验

  int *q[2];

  q[0]=&i;

  q[1]=&i;

  printf("%d\n",q[1][0]);//实验得出这不是个二维数组而是指针数组使用了[0]取值

 

那么同样*也可以对数组使用

 int a[]={1,3,2,42,7,};

  printf("*a=%d\n",*a);

把数组当指针用就可以了

指针与const

注:只适用于c99

表示一旦得到了某个变量的地址,不能再指向其他变量

例如:

int *const q=&I;

*q=26;//ok

q++;//error

 

所指是const

表示不能通过这个指针去修改那个变量(并不能使得那个变量成为const)

const int *p=&i;

*p=26;//error! (*p)const

i=26;//ok

p=&j;//ok

意思是变量并不是const,指针也可以指向别的变量,但是不能通过*p去改变变量的值

 

这些是啥意思?

判断哪个被const了的标志是const在*前面还是后面

如果在*前面表示它所指的东西不能(*p=?)被修改

如果在*后面表示指针不能被修改

 

转换

总是可以把一个(传进来的参数)非const的值转换成const的

有一个函数:void f(const int* x);

int a=15;

f(&a);//a的地址穿进去ok

 

const int b=a;

f(&b);//将一个本来就是const 的变量传进去也ok

 

但是在函数中执行

b+a+1;//error

 

当要传递的参数类型比地址大的时候,这是常用的手段:既能用比较少的字节数传递值给参数,又能避免函数对外面的变量进行修改

 

 

const数组

const int a[]={1,2,3,4,5,6};

数组变量已经是const的指针了,这里的const表明数组的每个单元都是const int

所以必须通过初始化进行赋值

 

保护数组值

因为把数组传入函数时传递的是地址,所以那个函数可以修改数组的值,为了保护数组不被函数破坏可以设置参数为const

int sum(const int a[],int length);

指针运算

 char ac[]={0,1,2,3,4,5,6,7,8,9,};

    char *p=ac;

    printf("p=%p\n",p);

    printf("p+1=%p\n",p+1);//sizeof(char)=1

    int ac2[]={0,1,2,3,4,5,6,7,8,9,};

    int *p2=ac2;

    printf("p2=%p\n",p2);

    printf("p2+1=%p\n",p2+1);//sizeof(int)=4

    printf("*p2+1=%d",*(p2+1));

    //所以指针加1就是指向数组的下一个单元,实际上加的是sizeof

    return 0;

 

*(p+1)-->a[1]

为什么要这么做?因为

直接将地址+1是无意义的,如果指针不是指向一片连续分配的空间如数组则这种运算没有意义,所以+1就是加一个sizeof

既然可以加则也可以减,p++,p--

 

两个指针相减

 char ac[]={0,1,2,3,4,5,6,7,8,9,};

    char *p=ac;

    char *p1=&ac[5];

    printf("p1-p=%d\n",p1-p);

    int ai[]={0,1,2,3,4,5,6,7,8,9,};

    int *q=ai;

    int *q1=&ai[5];

    printf("q1-q=%d\n",q1-q);

    return 0;

表示两个指针间能放多少个这样的变量

 

*p++

去除p所指的那个数据来完事之后顺便把p移到下一个位置去

*的优先级虽然高,但是没有++高

常用于数组类的连续空间操作

在某些cpu上,这可以直接被翻译成一条汇编指令

 

数组两种遍历方式

第一种

 printf("q1-q=%d\n",q1-q);

    for (int i = 0; i < sizeof(ai) / sizeof(ai[0]); ++i) {

        printf("%d\n",*q++);

    }

    q=ai;

第二种

    while (*q != -1){

        printf("%d\n",*q++);

    }

用指针来做什么

1、需要传入较大的数据时用作参数

2、传入数组后对数组做操作

3、函数返回不止一个结果

4、需要用函数来修改不止一个变量

5、动态申请的内存…

动态内存分配

输入数据问题:输入数据时,先告诉个数后再输入,要记录每个数据

c99可以用变量做数组定义的大小,C99之前呢?

 

使用动态内存分配

写法: int*a=(int*)malloc(n*size(int));

意思:malloc函数参数是需要的内存大小,n是要输入的变量数量,sizeof(int)代表要int所以是4个字节

最后申请出来的是void*类型,使用(int*)强制转换成int类型

例如:我要120个字节,就是30个int,30*sizeof(int)=120

 

使用该函数需要#include<stdlib.h>

参数类型是一个size_t 现在不讲

返回值是 void*

对于c语言来说,无法传递一个类型,只能告诉malloc要多少个字节

计组知识:1个字是的大小取决于地址线根数,也是一次传输能传送的最大位数,32位下一个字=4字节,64位下是=8字节

动态分配空间示例(重点)

intnumber;

int*a;

inti;

printf("输入数量:");

scanf("%d",&number);

//inta[number];//c99做法

a=(int*)malloc(number*sizeof(int));

//因为指针和数组是一样的,所以之后指针a就当做数组用就好了

for(i=0;i<number;i++)

{

scanf("%d",&a[i]);

}

for(i=number-1;i>=0;i--)//逆序遍历

{

printf("%d",a[i]);

}

//空间用完了要还给系统

free(a);

malloc和free成对出现,申请过的空间,最终都应该要还

free()把申请来的空间换给系统,但是只能还申请来空间的首地址

 void* p;

    p = malloc(100 * 1024 * 1024);

    p++;

    free(p);

如果如以上代码p++之后释放p,就会报错:要释放的指针不是申请来的

  void *p;

  int i;

  p=&i;

 free(p);//错误

同样不能释放定义的变量空间,且随便指定一个地址比如1也会报错

但是可以释放NULL,因为free函数里面有个判断如果地址是0则不作任何事情,所以定义指针时注意初始化为0

引用csdn的文章内容:

1.用malloc来分配的内存应该把它free掉,否则在那些空间不再使用时,程序仍然占用大量的内存.malloc可以单独出现,但是一般我们都不这样做!!

2.如果不是用malloc来分配的,就无需free,就是说,free不可以单独出现在程序中,否则会无缘无故的回收内存空间,后果将会很严重.

常见问题:

申请了没free会长时间运行内存逐渐下降

新手:忘了

老手:找不到合适的free时机

虽然程序结束所有的内存漏洞(垃圾)都会被操作系统清除,但是在大型项目里(比如服务器),就必须free。

free过了再free

地址变过来,直接去free

没空间了怎么办?

如果申请失败则返回0,或则叫做NULL

你的系统能给你多大的空间?

#include <stdio.h>

#include<stdlib.h>

int main() {

    void* p;

    int cnt = 0;

    while ((p = malloc(100 * 1024 * 1024))) {//10241k100*1024^2=100Mbwhile执行到p=0为止

        cnt++;

    }

    printf("分配了%d00MB的空间\n", cnt);

    return 0;

64位的结果

32位的结果

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值