C语言学习笔记(六): 探索函数与变量
指针变量
指针是一种特殊的变量,它存储的是某个变量的内存地址。指针变量可以存储内存地址,并且通过指针变量可以间接操作内存中的数据
include <stdio.h>
int main()
{
int a=1, * p; //定义指针变量,*是指针运算符
p = &a; //把a的地址赋给指针变量p,&是取地址运算符
printf("%d\n", *p); //以整数形式输出指针变量p所指向的变量的值,即a的值
*p = 2; //将整数1赋给p当前所指向的变量,由于p指向变量a,相当于把1赋给a,即a=2
printf("a=%d,a的地址是%d",a,p); //以十进制形式输出指针变量p的值,即输出变量a的地址;a的值变为了2
}
通过指针引用数组
数组元素的指针
一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组元素。
若指针变量直接指向数组变量名,则表示指向数组第一个元素的地址。
int a[10]={1,3,5,7,9,11,13,15,17,19}; //定义a为包含10个整型数据的数组
int *p = &a[0]; //定义一个整型指针变量,并指向整型数组
int a[10]={1,3,5,7,9,11,13,15,17,19};
int *p = a; //等价于int *p = &a[0];
数组元素里指针的运算
在指针已指向一个数组元素时,指针可以进行以下运算:
- p+1:表示指向同一数组的下个元素
- p-1:表示指向同一数组的上个元素
- p++,p--:指针的自加自减运算
若p的初值是a(即&a[0]),则p+i和a+i就是数组元素a[i]的地址,它俩指向a[i]
*(p+i)或*(a+i)是p+i或a+i指向的数组元素值,即a[i]
include <stdio.h>
int main()
{
int a[10] = { 0,1,2,3,4,5,6,7,8,9 };
int *p = a;
//下述三个输出结果均为2
printf("%d", *(p + 2));
printf("%d", *(a + 2));
printf("%d", a[2]);
}
通过数组名作函数参数
以变量名和数组名作为函数参数的比较
int main()
{ void fun(int arr[], int n); //对fun函数的声明
int array[10]; //定义array数组
⋮
fun(array,10); //array是实参,arr是形参,
return 0;
}
void fun (arr[ ],int n)
{ printf(″%d\n″, *arr); //输出array[0]的值
arr=arr+3; //形参数组名可以被赋值
printf(″%d\n″, *arr); //输出array[3]的值
}
通过指针引用字符串
字符串的引用方式
/*通过定义字符串数组*/
include <stdio.h>
int main()
{ char string[]="I love China!"; //定义字符数组string
printf("%s\n",string); //用%s格式声明输出string,可以输出整个字符串
printf("%c\n",string[7]); //用%c格式输出一个字符数组元素,输出'C'
return 0;
}
字符串指针作函数参数
将字符串指针作为函数参数, 有以下四种传递方式
实参 | 形参 |
---|---|
字符数组名 | 字符数组名 |
字符数组名 | 字符指针变量 |
字符指针变量 | 字符指针变量 |
字符指针变量 | 字符数组名 |
下述代码用于实现字符串拷贝
include <stdio.h>
int main()
{ void copy_string(char from[], char to[]); //函数声明
char a[]="I am a teacher."; //定义字符数组a并初始化
char b[]="You are a student."; //定义字符数组b并初始化
char *from=a,*to=b; //from指向a数组首元素,to指向b数组首元素
printf("string a=%s\nstring b=%s\n",a,b);
printf("copy string a to string b:\n");
copy_string(from,to); //实参为字符指针变量
printf("\nstring a=%s\nstring b=%s\n",a,b);
return 0;
}
void copy_string(char from[], char to[]) //形参为字符数组
{ int i=0;
while(from[i]!='\0')
{ to[i]=from[i]; i++;}
to[i]='\0';
}
指向函数的指针
什么是函数的指针
函数名就是函数的指针,它代表函数的起始地址。
函数指针变量调用函数
/*判断两数的大小*/
include <stdio.h>
int main()
{ int max(int,int); //函数声明
int (*p)(int,int); //定义指向函数的指针变量p,表示指向函数类型为整型且有两个整型参数的函数
int a,b,c;
p=max; //使p指向max函数
printf("please enter a and b:");
scanf("%d,%d",&a,&b);
c=(*p)(a,b); //通过指针变量调用max函数
printf("a=%d\nb=%d\nmax=%d\n",a,b,c);
return 0;
}
int max(int x,int y) //定义max函数
{ int z;
if(x>y)z=x;
else z=y;
return(z);
}
指针数组
什么是指针数组
一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都存放一个地址,相当于一个指针变量。
如下代码定义了一个指针数组, 用于存放int类型的指针元素
int *p[4];
使用实例
include <stdio.h>
int main()
{
int a[5] = { 1,3,5,7,9 };
int* num[5] = { &a[0],&a[1],&a[2],&a[3],&a[4] };
int** p, i; //p是指向指针型数据的指针变量
p = num; //使p指向num[0],即p指向&a[0]
for (i = 0; i < 5; i++)
{
printf("%d ", **p); //*p=&a[0] **p=a[0]
p++;
}
printf("\n");
return 0;
}
动态内存分配
定义
全局变量是分配在内存中的静态存储区的,非静态的局部变量(包括形参)是分配在内存中的动态存储区的
除此以外,C语言还允许建立内存动态分配区域,以存放一些临时用的数据,这些数据不必在程序的声明部分定义,也不必等到函数结束时才释放,而是需要时随时开辟,不需要时随时释放。这些数据是临时存放在一个特别的自由存储区,称为堆(heap)。可以根据需要,向系统申请所需大小的空间。
由于未在声明部分定义它们为变量或数组,因此不能通过变量名或数组名去引用这些数据,只能通过指针来引用
动态分配内存的函数
malloc函数
该函数是一个指针型函数,返回的指针指向该分配域的第一个字节
/* void *malloc(unsigned int size); */
int *p = malloc(100); //开辟100字节的临时分配域,函数值为其第1个字节的地址;若函数执行失败(如内存空间不足),则返回空指针(NULL)
calloc函数
在内存的动态存储区中分配n个长度为size的连续空间,这个空间一般比较大,足以保存一个数组。
/* void *calloc(unsigned n,unsigned size); */
p=calloc(50,4); //开辟50×4个字节的临时分配域,把首地址赋给指针变量p;若执行失败返回NULL
realloc函数
如果已经通过malloc函数或calloc函数获得了动态空间,想改变其大小,可以用realloc函数重新分配。
/* void *realloc(void *p,unsigned int size) */
realloc(p,50); //将p所指向的已分配的动态空间改为50字节;失败则返回NULL
free函数
是释放指针变量p所指向的动态空间,使这部分空间能重新被其他变量使用。p应是最近一次调用calloc或malloc函数时得到的函数返回值
free(p); //释放指针变量p所指向的已分配的动态空间,无返回值
使用实例
建立动态数组,输入5个学生的成绩,另外用一个函放数检查其中有无低于60分的,输出不合格的成绩
include <stdio.h>
include <stdlib.h> //程序中用了malloc函数,应包含stdlib.h
int main()
{
void check(int*); //函数声明
int* p1, i; //p1是int型指针
p1 = (int*)malloc(5 * sizeof(int)); //开辟动态内存区,(int *)表示强制指针类型转换
for (i = 0; i < 5; i++)
scanf("%d", p1 + i); //输入5个学生的成绩
check(p1); //调用check函数
return 0;
}
void check(int* p) //定义check函数,形参是int*指针
{
printf("They are fail:");
for (int i = 0; i < 5; i++)
if (p[i] < 60) printf("%d \0", p[i]); //输出不合格的成绩
}
指针总结
变量定义 | 含义 |
---|---|
int i |
定义整型变量i |
int *p |
定义p为指向整型数据的指针变量 |
int a[5] |
定义整型数组a,它有5个元素 |
int *p[4] |
定义指针数组p,它由4个指向整型数据的指针元素组成 |
int (*p)[4] |
p为指向包含4个元素的一维数组的指针变量 |
int *p() |
p为返回一个指针的函数,该指针指向整型数据 |
int (*p)() |
p为指向一个返回值为整数的函数的指针 |
int **p |
p是一个指针变量,它指向一个指向整型数据的指针变量 |
void *p |
p是一种指向任意类型数据的通用指针。它可以指向任意类型的数据,但是不能通过该指针直接访问数据,需要先转换为特定的指针类型再访问 |