变量和作用域、指针
指针变量
指针变量只能用来记录地址数据,因为地址数据和普通数据的使用方法不同,所以指针变量和普通变量使用方法不同,指针变量的主要用途就是找到一个普通变量的存储区(老年机打电话找智能机)。只有当指针里记录了存储区的地址后才可以通过这个指针找到那个存储区。
声明指针变量的时候需要在指针变量名称前加,如果一个指针记录了一个存储区的地址就可以认为他们之间实现了捆绑关系,当一个指针记录了某个存储区的地址后就可以在指针前使用 * 操作符找到捆绑的存储区。
声明指针时的类型名称用来表示指针适合与什么类型的存储区捆绑,可以在一条语句里声明多个类型的指针变量,这个时候必须在每个指针变量名称前单独加 *。没有捆绑的指针分为两种,一种叫做空指针,它固定记录空地址(NULL),这个地址的数值就是0 ;其他没有捆绑的指针都叫做野指针。
程序里不可以出现野指针,指针变量必须初始化,指针变量初始化的时候*没有参与赋值过程,指针和存储区的捆绑关系可以随着程序的执行不断变化。这种使用方法里可以把指针看作存储区的某种身份或者代表了存储区的某种特征。
指针和数组关系
如果一个指针和数组里的第一个存储区捆绑就可以通过这个指针找到数组里的每个存储区,地址数据可以参与如下计算过程。
地址 + 整数 地址 - 整数 地址 - 地址
地址加减整数n实际上加减的是n个捆绑存储区的大小,数组里第一个存储区的地址加下标可以得到下标对应存储区的地址,以下写法也可以用来表示数组里的存储区
*(arr + num)
其中arr是数组名称,num是下标,地址之间做减法结果是一个整数,这个整数表示两个地址之间包含的捆绑存储区个数。可以使用指针变量作为循环变量编写for循环依次处理数组里的每个存储区。
const关键字
声明指针变量的时候可以使用const关键字,声明指针变量的时候可以把const关键字写在类型名称前,不可以通过这种指针对捆绑存储区做赋值,但是可以对这种指针本身做赋值;声明指针变量的时候可以把const关键字写在指针变量名称前,可以通过这种指针对捆绑存储区做赋值,但是不可以对这种指针本身做赋值(这种用的少)。
void关键字
声明指针变量的时候可以使用void作为类型名称,这种指针可以叫做无类型指针,这种类型的指针可以和任意类型的存储区捆绑,无法通过无类型指针知道它捆绑存储区的类型,不应该在无类型指针前直接加*,也不应该对无类型指针进行加减整数的计算。
必须先把无类型指针强制转换成有类型指针然后才能使用,所有跨函数使用存储区都是通过指针实现的,数组做形式参数的时候真正的形式参数就是一个指针,如果函数不会修改指针形式参数所捆绑存储区的内容就应该在声明指针形式参数的时候在类型名称前加const关键字。
无类型指针通常用来作为形式参数使用,采用无类型指针作为形式参数可以把任意类型的数据传递给被调用函数。
练习:编写函数把主函数里两个变量内容交换
/*
*
*主函数变量内容交换
*
*
* */
#include<stdio.h>
void swap (int *p_num,int *p_num1){
int tmp = *p_num;
*p_num = *p_num1;
*p_num1 = tmp;
}
int main (){
int num = 3, num1 = 2;
swap (&num ,&num1);
printf("num =%d ,num1 = %d\n",num,num1);
return 0;
}
被调用函数使用存储区的地址做返回值可以让调用函数使用被调用函数的存储区,被调用函数需要提供一个指针类型的存储区用来存放作为返回值的地址数据。不可以把非静态局部变量存储区的地址当返回值使用。
练习:编写函数从一个数组里找到最大数字所在的存储区并把这个存储区传递给调用函数。
/*
*
*指针练习
*
* */
#include<stdio.h>
int *max (const int *p_num,int size){
const int *p_tmp = NULL,*p_max = NULL;
for(p_tmp = p_num;p_tmp <= p_num + size -1;p_tmp++){
if (!p_max){
p_max = p_tmp;
}
else {
if (*p_tmp > *p_max){
p_max = p_tmp;
}
}
}
return (int *)p_max;
}
int main (){
int arr[] = {1,2,3,4,5};
int *p_num = max(arr,5);
printf("%d\n",*p_num);
return 0;
}
点击查看代码
#if 0
/*
*
*指针声明
*
* */
#include<stdio.h>
int main (){
int num = 0;
int *p_num = NULL,*p_num1 = NULL; // 指针变量声明
p_num = #
*p_num = 10;
printf("%d\n",num);
return 0;
}
#elif 0
/*
*
*指针演示
*
* */
#include<stdio.h>
int main (){
int arr[] = {1,2,3,4,5};
int *p_num = arr;
int num = 0;
for (num = 0;num <= 4;num++){
printf("%d ",arr[num]);
printf("%d ",p_num[num]);
printf("%d ",*(arr + num));
printf("%d ",*(p_num + num));
}
printf("\n");
return 0;
}
#elif 0
#include<stdio.h>
int main (){
int arr[] = {1,2,3,4,5};
printf("arr是%p\n",arr);
printf("arr+2是%p\n",arr + 2);
printf("&arr[2]是%p\n",&arr[2]);
printf("arr-2是%p\n",arr - 2);
printf("&arr[2]-arr是%ld\n",&arr[2] - arr);
return 0;
}
#elif 0
/*
*
*指针演示
*
* */
#include<stdio.h>
int main (){
int arr[] = {1,2,3,4,5};
int *p_tmp = NULL;
for (p_tmp = arr;p_tmp <= arr + 4;p_tmp++){
printf("%d",*p_tmp);
}
printf("\n");
return 0;
}
#elif 0
/*
*
*const
*
* */
#include<stdio.h>
int main (){
int num = 0;
const int *p_num = #
int * const p_num1 = #
//*p_num = 10; //只读,错误
p_num = NULL;
*p_num1 = 10;
p_num1 = NULL;
return 0;
}
#elif 0
/*
*
*
*无类型指针
*
* */
#include<stdio.h>
int main (){
char ch = 'r';
int num = 23;
float fnum = 5.4f;
void *p_v = &ch;
printf("%c\n",*(char *)p_v);
p_v = &fnum;
printf("%g\n",*(float *)p_v);
p_v = #
printf("%d\n",*(int *)p_v);
return 0;
}
#elif 0
/*
*
*指针形式参数
*
* */
#include<stdio.h>
void print (const int *p_num,int size){ //const为了告诉调用函数给的存储区内容不会修改
int num = 0;
for (num = 0;num <= size - 1;num++){
printf("%d ",*(p_num + num));
}
printf("\n");
}
int main (){
int arr[] = {1,2,3,4,5};
print(arr,5);
return 0;
}
#elif 0
/*
*指针形式参数
*
* */
#include<stdio.h>
void print (const void *p_v,int type){
if (!type){
printf("%c\n",*(const char *)p_v);
}
else if (type == 1){
printf("%d\n",*(const int *)p_v);
}
else if (type == 2){
printf("%g\n",*(const float *)p_v);
}
}
int main (){
char ch = 'r';
int num = 34;
float fnum = 3.4f;
print(&ch,0);
print(&num,1);
print(&fnum,2);
return 0;
}
#elif 0
/*
*
*主函数变量内容交换
*
*
* */
#include<stdio.h>
void swap (int *p_num,int *p_num1){
int tmp = *p_num;
*p_num = *p_num1;
*p_num1 = tmp;
}
int main (){
int num = 3, num1 = 2;
swap (&num ,&num1);
printf("num =%d ,num1 = %d\n",num,num1);
return 0;
}
#elif 0
/*
*
*地址返回值演示
*
* */
#include<stdio.h>
/*int *read (void){
static int num = 0;
printf("请输入一数字");
scanf("%d",&num);
return #
}
*/
int *read (int *p_num){
printf("请输入一数字");
scanf("%d",p_num);
return p_num;
}
int main (){
//int *p_num = read();
int num = 0;
int *p_num = read(&num);
printf("%d\n",*p_num);
return 0 ;
}
#elif 1
/*
*
*指针练习
*
* */
#include<stdio.h>
int *max (const int *p_num,int size){
const int *p_tmp = NULL,*p_max = NULL;
for(p_tmp = p_num;p_tmp <= p_num + size -1;p_tmp++){
if (!p_max){
p_max = p_tmp;
}
else {
if (*p_tmp > *p_max){
p_max = p_tmp;
}
}
}
return (int *)p_max;
}
int main (){
int arr[] = {1,2,3,4,5};
int *p_num = max(arr,5);
printf("%d\n",*p_num);
return 0;
}
#endif