[C++系列] C语言基础 day10 指针
in C/C++ with 0 comment

[C++系列] C语言基础 day10 指针

in C/C++ with 0 comment

#指针

指针变量用来记录地址数据
只有记录有效地址的指针才能使用
声明指针变量的时候需要在变量名称前加*
有效的指针变量前使用*操作符可以表示指针捆绑的存储区

指针变量也分类型,不同类型的指针适合与不同类型的存储区捆绑。
可以在一条语句里声明多个同类型的指针变量,这个时候要在每个指针变量名称前加*

#没有捆绑的指针分为两类
1,空指针里面记录空地址(NULL),这个地址的数值为0;
2,其它没有捆绑的指针叫做野指针。

程序里竞争出现野指针。
所有指针变量必须初始化。
指针变量初始化的时候*没有参与赋值过程。

#练习

#使用指针将3个数字从小到大排列。

1 #include<stdio.h>
2
3 int main(){
4 int num =3,num1 =2,num2=5,tmp=0;;
5 int *p_num = &num,*p_num1 = &num1,*p_num2=&num2,*p_tmp=&tmp;
6 if(*p_num > *p_num1){
7 p_tmp = p_num;
8 p_num =p_num1;
9 p_num1 = p_tmp;
 10 }
 11 if(*p_num > *p_num2){
 12 p_tmp = p_num;
 13 p_num = p_num2;
 14 p_num2 = p_tmp;
 15 }
 16 if(*p_num1 > *p_num2){
 17 p_tmp = p_num1;
 18 p_num1 = p_num2;
 19 p_num2 =p_tmp;
 20 }
 21 printf("%d  %d  %d\n",*p_num,*p_num1,*p_num2);
 22
 23 return 0;
 24 }

指针和存储区的捆绑关系可以随着程序的执行不断变化。
这种时候可以把指针看作是变量的某种身份。

#指针和数组

如果指针记录数组里第一个存储区的地址就可以通过这个指针找到数组里的每个存储区。
可以通过在指针后加下标的方式表示数组里的存储区

#include<stdio.h>
int main(){
int arr[] = {1,2,3,4,5};
int *p_num = arr;
for(int i=0;i<=4;i++){
printf("%d ",arr[i]);

}
printf("\n");
for(int i=0;i<=4;i++){
printf("%d “,*(p_num+num));
}
return 0;
}include<stdio.h>

#地址数据的计算规则

地址数据可以参与如下运算过程:
1,地址+整数
2,地址-整数
3,地址-地址

地址加减整数N实际上加减的是n个捆绑存储区的大小
地址减地址的结果是两个地址之间包含的捆绑存储区个数。

#例:

#include<stdio.h>

int main(){
int arr[] = {1,2,3,4,5};
printf("arr : %p , arr+3: %p ,arr -3 : %p \n",arr,arr+3,arr-3);
return 0;
}

数组名称加下标可以得到下标对应存储区地址。
以下写法也可以用来表示数组里的某个存储区。 *(arr+num) arr表示数组名称,num表示下标

可以使用指针变量作为循环变量编写for循环依次处理数组里的每个存储区。

#include<stdio.h>
int main(){
int *p_num = NULL;
int arr[]={1,2,3,4,5};
for(int i=0;i<=4;i++){
printf("%d ",arr[i]);
}
printf("\n");
for(p_num = arr;p_num <= arr+4;p_num++){
printf("%d ",*(p_num));
}
printf("\n");
return 0;
}

声明指针变量的时候可以使用const关键字
如果声明指针变量的时候在指针【类型】名称前使用const关键字就表示不可以通过这个指针对它捆绑的存储区做赋值,但可以对指针本身做赋值。
如果声明指针变量的时候在指针变量名称前使用const关键字就可以通过这个指针对它所捆绑的存储区赋值,但是不能对这个指针本身做赋值。

#include<stdio.h>
int main(){
int num =0;
const int *p_num =&num;
int * const p_num1 = &num;
// 错误 *p_num = 10; //通过这个指针对捆绑的存储区赋值
p_num = NULL;
*p_num1 =10;
return 0;
}

声明指针变量的时候可以使用void作为类型名称
这种指针可以叫做无类型指针
void *p_v = NULL;
这种指针可以和任意类型的存储区捆绑
无法通过这种指针知道捆绑存储区的类型
不应该在这种指针前面直接使用*操作符
也不应该对着种指针进行加减整数的计算
这种指针必须首先强制类型转换成有类型指针,然后再使用

## `#`例子:
#include<stdio.h>

int main(){
    char ch ='r';
    int num = 34;
    float fnum =5.4f;
    void *p_v = NULL;
    p_v = &ch;
    printf("%c\n",*(char *)p_v);
    p_v = &num;
    printf("%d\n",*(int *)p_v);
    p_v = &fnum;
    printf("%g\n",*(float *)p_v);
    return 0;
}

#指针应用

所有跨函数使用存储区都必须通过指针来实现。
数组做形式参数的时候真正的形式参数其实是一个指针。

#include<stdio.h>
int arr[] ={1,2,3,4,5};
void print(int *p_num,int size){
    for(int i=0;i<=size-1;i++){
        printf("%d  ",*(p_num+i));
    }
}
int main(){
    print(arr,5);
    return 0;
}

#练习

编写函数把主函数里两个变量的内容交换。

#include<stdio.h>
void exchange(int *p_num,int *p_num1){
    int tmp;
    tmp = *p_num;
    *p_num = *p_num1;
    *p_num1 =tmp;

}
int main(){
    int num = 8,num1 = 9;
    exchange(&num,&num1);
    printf("%d   %d",num,num1);
    return 0;
}

注意:
声明指针形式参数的时候,尽量在类型名称前加const关键字。

#例子:

#include<stdio.h>
int arr[] ={1,2,3,4,5};
void print(const int *p_num,int size){
for(int i=0;i<=size-1;i++){
printf("%d  ",*(p_num+i));
}
}
int main(){
print(arr,5);
return 0;
}

无类型指针通常当作函数的形式参数使用。
使用无类型函数形式参数可以使用多种函数参数。

被调用函数使用存储区的地址做返回值就可以让调用函数使用被调用函数提供的存储区。
这个时候被调用函数需要提供一个指针类型的存储区记录作为返回值的地址。
绝对不可以把非静态局部变量的地址作返回值使用

#include<stdio.h>
int *read(void){
static int num = 0;
printf("输入一个数字:\n");
scanf("%d",&num);
return &num;
}
int main(){
int *p_num = read();
printf("%d",*p_num);
return 0;
}include<stdio.h>

#include<stdio.h>
/*
int *read(void){
static int num = 0;
printf("输入一个数字:");
scanf("%d",&num);
return &num;
}
*/
int *read(int *p_num){
printf("输入一个数字:");
scanf("%d",p_num);
return p_num;
}
int main(){
int num = 8;
int *p_num = read(&num);
printf("%d",*p_num);
return 0;
}

练习

编写函数从一个数组里找到最大数字所在的存储区并把这个存储区传递回调用函数。

#include<stdio.h>
int *getmax(const int *p_num,int size){
const int *p_tmp = NULL;
const int *p_max = NULL;
//static int max = 0;
for(p_tmp=p_num;p_tmp<=p_num+size;p_tmp++){
    if(!p_max || *p_tmp > *p_max){
       p_max = p_tmp;
    }
}

    return (int *)p_max;
}
int main(){
int arr[] ={1,2,3,7,5,53,46,49};
int *max = getmax(arr,8);
printf("%d",&max);
return 0;
}

预习

Responses