参考.
重点关注:
(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;
}