C语言 -- 指针基础 -- 参考翁恺C语言程序设计

参考.

重点关注:
(1)malloc动态申请内存空间时,返回的值是void*类型,需要强制转换为自己需要的类型。
(2)回调函数。
(3)使用指针的方法,使函数返回多个值。

每一个变量都有一个内存位置,每一个内存位置都定义了可使用“&”运算符访问的地址。
eg:

#include<stdio.h>
int main()
{
   int i=10;
   int *a = &i;
   int *b = &i;
   
   printf("i的地址是%p\n", &i);
   printf("%p\n", a);
   printf("%d\n", *a);

   b++;
   printf("b的地址是%p\n", b);

   return 0;
}

输出为:

i的地址是0x7ffc9ca80d84
0x7ffc9ca80d84
10
b的地址是0x7ffc9ca80d88

指针是一个变量,其值为另一个变量的地址。

就像其他变量或常量一样,需要在使用指针存储其他变量地址之前对其进行声明
eg:

int *p;

*号:在这里表示p是一个指针,指向一个int。

#include<stdio.h>

void f(int *p);
void g(int k);

int main()
{
   int i=6;
   printf("&i=%p\n", &i);
   f(&i);                         //&i这个地址值被传进了函数f(),通过这个地址,我们可以在函数内部访问外部的变量i。
   g(i);

   return 0;
}

void f(int *p)
{
   printf(" p=%p\n", p);
   printf("*p=%d\n", *p);
   *p=26;                         //p的值就是i的地址,*p就代表i。这样就可以修改i。
}

void g(int k)
{
   printf("k=%d\n", k);
}

输出为:

&i=0x7ffdc600bb24
 p=0x7ffdc600bb24
*p=6
k=26

指针的运算符:&和*

&表示取地址;*表示取得地址所代表的变量。
这两个运算符是互相反作用的。

指针应用场景

一a、函数返回多个值

#include<stdio.h>

void minmax(int a[], int len, int *max, int *min);         //函数的返回值只能返回一个值,所以这里用两个指针来实现。

int main(void)
{
   int a[]={1,2,3,4,5,6,7,8,9,12,13,14,16,17,21,23,55,};
   int min,max;
   minmax(a, sizeof(a)/sizeof(a[0]), &min, &max);          //sizeof(a)/sizeof(a[0])得到元素的个数并传给len,然后将变量min和max取地址并交给minmax()函数。
   printf("min=%d,max=%d\n", min ,max);

   return 0;
}

void minmax(int a[], int len, int *min, int *max)
{
   int i;
   *min=*max=a[0];
   for(i=1;i<len;i++)
   {
      if(a[i]<*min)
      {
         *min=a[i];
      }
      if(a[i]>*max)
      {
         *max=a[i];
      }
   }
}

输出为:

min=1,max=55

一b、

#include<stdio.h>

int divide(int a, int b, int *result);

int main(void)
{
	int a=5;
	int b=2;
	int c;
	if(divide(a,b,&c))
	{
		printf("%d/%d=%d\n", a, b, c);
	}
	return 0;
}

int divide(int a, int b, int *result)
{
	int ret=1;
	if(b==0)
	{
		ret=0;
	}
	else
	{
		*result = a/b;
	}
	return ret;
}

输出为:

5/2=2

指针运算(可以先略)

#include<stdio.h>

int main(void)
{
   char a[]={0,1,2,3,4,5,6,};
   char *p= a;
   char *p1=&a[5];
   printf("p=%p\n", p);
   printf("p+1=%p\n", p+1);         // 这里,当p指向a后,*(p+n)和a[n]等价。
   printf("*(p+1)=%d\n", *(p+1));
   printf("p1-p=%d\n",p1-p);

   int b[]={0,1,2,3,4,5,6,};
   int *q= b;
   int *q1=&b[4];

   printf("q=%p\n", q);
   printf("q+1=%p\n", q+1);
   printf("*(q+1)=%d\n", *(q+1));
   printf("q1-q=%d\n",q1-q);

   return 0;
}

输出为:

p=0x7ffd374be881
p+1=0x7ffd374be882
*(p+1)=1
p1-p=5
q=0x7ffd374be860
q+1=0x7ffd374be864
*(q+1)=1
q1-q=4

解释:sizeof(char)=1,sizeof(int)=4。所以当我们给一个指针加1时,不是在地址值上加1,而是在地址值上加一个“sizeof(指针所指的类型)”。两个指针相减=两个地址的差 / sizeof(指针的类型)。
对于char和int类型的数组,如果是char的数组,它的第一个单元的地址是51,则第二个单元的地址是52。如果是int类型的数组,int数组的一个单元要占据4个字节,所以它的第一个单元的地址是30,则它的第二个单元的地址是34。

数组变量是特殊的指针

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

#include<stdio.h>
int main(void)
{
   int a[]={1,2,3,4,5,}; 
   printf("a[0]=%d\n", a[0]);

   int *p=a;                          //数组本身表达地址,所以无需用 & 取地址。
   int *p = &a[0];                   //但是数组的单元表达的是变量,需要用 & 取地址。
   //上边这两行表达的是一个意思,即a[0]的地址就代表a的地址。
   printf("*p=%d\n", *p);
   printf("p[0]=%d\n", p[0]);        // “[]" 运算符可以对数组做,也可以对指针做。
   printf("*a=%d\n", *a);            // “*" 运算符可以对指针做,也可以对数组做。
}

输出为:

a[0]=1
*p=1
p[0]=1
*a=1

一个数组是常量(const)指针,所以这个数组不能被赋值。

指针数组

如果我们想让数组存储指向某一数据类型的指针,下面是一个指向整型变量的指针数组的声明:

int *ptr[MAX];

在这里,把ptr声明为一个数组,由MAX个整型指针组成。因此,ptr中的每个元素,都是指向int值的指针。

#include <stdio.h>
 
const int MAX = 3;
 
int main ()
{
   int  var[] = {10, 100, 200};
   int i, *ptr[MAX];
 
   for ( i = 0; i < MAX; i++)
   {
      ptr[i] = &var[i]; /* 赋值为整数的地址 */
   }
   for ( i = 0; i < MAX; i++)
   {
      printf("Value of var[%d] = %d\n", i, *ptr[i] );
   }
   return 0;
}

编译执行后,

Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200

动态内存分配

在这里插入图片描述

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

int main(void)
{
	int number;
	int *a;
	int i;
	printf("输入数量:");
	scanf("%d", &number);
	a = (int*)malloc(number*sizeof(int));   //一旦用malloc得到了那块空间并交给了a,之后就可以把a当做一个数组来操作
	for(i=0;i<number;i++){
		scanf("%d",&a[i]);
	}
	for(i=0;i<number;i--){   //逆序输出这些数字
		printf("%d",a[i]);
	}
	free(a);     //把申请得来的空间还回去
	return 0;
}
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	void *p;
	int cnt = 0;
//用malloc申请100MB空间,这里做了两个操作:一个是把malloc的结果赋给了p,一个是p得到的值拿来做while判断。
//如果p得到的不是0,那么就意味着它得到的是一个有效的地址,继续进行cnt++;如果是0,退出while。
	while ((p=malloc(100*1024*1024))){    
		cnt++;                        
	}
	printf("分配了%d00MB的空间\n",cnt);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值