作业整理;
指针的基本的结构与基础知识整理;
作业讲解:
(1) 将2~100之间的素数 保存到数组中,并遍历输出,每五行一个
include<stdio.h> #define N 50 int main() { int arr[N]; int i=2; int j=0; int k=0; for(i=2;i<100;++i) { for(j=2;j<i;j++) { //从2开始遍历,查找能被i整除的数, //若找到则跳出内层循环 if(i%j==0) break; } //若i==j,则i是素数,否则不是 if(i==j) { arr[k]=i; k++; printf("%4d",i); if(k%5==0) printf("\n"); } } }
(2) 在一个升序或降序排列的数组中,插入一个元素;提示:数组元素部分初始化
(按升序或降序)至少空一个位置存放要插入的数据。插入元素后,仍然是按升序或降序排列
include<stdio.h> int main() { int arr[5]={10,9,12,8}; int i,j,k,temp; printf("插入一个数:\n"); for(i=0;i<5;i++) if(arr[i]==0) scanf("%d",&arr[i]); for(k=0;k<5;k++) { for(j=0;j<5;j++) { if(arr[k]<arr[j]) { temp=arr[j]; arr[j]=arr[k]; arr[k]=temp; } } } for(i=0;i<5;i++) printf("%4d ",arr[i]); }
(3)互换数
include<stdio.h> int main() { int arr[5]; int i,temp; printf("请输入五位数:\n"); for(i=0;i<5;i++) scanf("%d",&arr[i]); temp=arr[0]; arr[0]=arr[4]; arr[4]=temp; temp=arr[1]; arr[1]=arr[3]; arr[3]=temp; for(i=0;i<5;i++) printf("%d\n",arr[i]); }
一、数组
1、二维数组 行数可以省略,列不可以省!! #include<stdio.h> int main() { //以下初始方法均可 int arr[][3]={1,2,3,4,5,6,7,8,9}; //int arr[3][3]={1,2,3,4,5,6,7,8,9}; //int arr[][3]={1,2,3,4,5}; //int arr[][3]={0}; //遍历输出二维数组 int i=0; int j=0; for(i=0;i<3;i++) { for(j=0;j<3;j++) { arr[i][j]=3*i+1; //或者手动输入 //scanf("%d",arr[i][j]); } } for(i=0;i<3;i++) { for(j=0;j<3;j++) { //printf("arr[%d][%d]=%d",i,j,arr[i][j]); printf("%4d",arr[i][j]); } printf("\n"); } }
求二维数组的总和余平均值
include<stdio.h> int main() { int arr[][3]={1,2,3,4,5,6,7,8,9}; int i,j,sum=0; float k=0; for(i=0;i<3;i++) for(j=0;j<3;j++) { sum=sum+arr[i][j]; } k=(float)sum/9; printf("sum=%d k=%f\n",sum,k); printf("===========================\n"); //每行 的总和即平均值 int sum1=0; float k1=0; //平均值 for(i=0;i<3;i++) { sum1=0; for(j=0;j<3;j++) { sum1=sum1+arr[i][j]; } k1=(float)sum1/3; printf("sum1=%d k1=%f\n",sum1,k1); } printf("===========================\n"); //每列 的总和即平均值 int sum2=0; float k2=0; //平均值 for(i=0;i<3;i++) { sum2=0; for(j=0;j<3;j++) { sum2=sum2+arr[j][i]; } k2=(float)sum2/3; printf("sum2=%d k2=%f\n",sum2,k2); } }
二、指针
(1) 指针类型是一种特殊类型三种定义类型:DataType name;DataType name;DataType * name; *:是指针的标志name: 变量名指针和普通变量的区别:指针:存地址普通变量:存值指针只能保存与其相同类型的地址int *p; 只能保存int 型地址char *pc; 只能保存char 型地址double *pd; 只能保存double 型地址
(2) 指针初始化
int *p=NULL; //ok
int a=3; //okint *pa=&a;
int *pb; //okpb=&a;
int ****pc; //这种赋值error *pc=&a;
include<stdio.h> int main() { int num=6; //NULL是一个空地址 是一个宏 int *pa=NULL; int *pb=# 把num 的地址赋给pb, *号是取pb指向地址里面的值 int pc; pc=# int pb; //错误 不能这样赋值 pb=# 地址的访问 //地址 printf("&num=%p\n",&num); printf("pb=%p\n",pb); //元素的访问 printf("num=%d\n",num); //+pb是取地址的值 而pb里面是&num的地址, printf("pb=%d\n",pb); }
(3) 地址的访问
int a=10; int pb; pb=&a; 变量名 变量地址 变量值 a 0x00012 10 pb 0x00024 0x000012 pb:取指针对应内存里面的值 可以把指针变量赋值给同类型指针 #include<stdio.h> int main() { int p=NULL; // printf("p=%p\n",p); //空地址不能访问里面的值 // printf("p=%d\n",p);//error内存泄漏 核心转储 int a=10; int pa=&a; printf("&a=%p\n",&a); printf("p=%p\n",p); printf("&p=%p",&pa); printf("a=%d\n",a); printf("pa=%d\n",pa); } #include<stdio.h> int main() { int p=10; //error 不能将常量直接赋值给指针变量 printf("p=%p\n",p); printf("p=%d\n",p);//内存中并未分配0xa这块内存 int a=12; int pa=&a; int pb; pb=pa; //可以把指针变量赋值给同类型指针 printf("pa=%p\n",pa); printf("pb=%p\n",pb); printf("pa=%d\n",pa); printf("pa=%d\n",*pa); //强制类型转化 临时转化 并不改变pa的属性 char pc=(char )pa; printf("pc=%d\n",pc); }
(4) 64位机下所有指针大小为8 32位机为4
一般情况写4#include<stdio.h>int main(){ printf("sizeof(char *)=%ld\n",sizeof(char *)); printf("sizeof(short *)=%ld\n",sizeof(short *)); printf("sizeof(int *)=%ld\n",sizeof(int *)); printf("sizeof(long *)=%ld\n",sizeof(long *)); printf("sizeof(float *)=%ld\n",sizeof(float *)); printf("sizeof(double *)=%ld\n",sizeof(double *));}结果: sizeof(char *)=8 sizeof(short *)=8 sizeof(int *)=8 sizeof(long *)=8 sizeof(float *)=8 sizeof(double *)=8
(5) 指针的类型和指针所指向的类型int *pa;double pd;指针的类型: 是类型+ 如 int 指针所指向的类型 :就是类型 int一句话就是指针的类型int 指向的是int类型
二、 指针与数组
(1) 数组名是一个地址 数组元素的访问的方法: int arr[5]={1,2,3,4,5}; int *pa=arr; arr[0]; arr[3]; *(arr); (arr+3); (pa); (pa+3); pa[0]; pa[3]; #include<stdio.h> int main() { int arr[5]={1,2,3,4,5}; //数组名表示的是一个地址 int pa=arr; printf("===========================\n"); printf("arr=%p\n",arr); printf("&arr[0]=%p\n",&arr[0]); printf("pa=%p\n",pa); printf("===========================\n"); //地址是一样的 printf("arr+1=%p\n",arr+1); printf("pa+1=%p\n",pa+1); //地址是一样的 printf("===========================\n"); printf("arr+2=%p\n",arr+2); printf("pa+2=%p\n",pa+2); //地址里面的值是一样的 printf("===========================\n"); printf("(arr+2)=%d\n",(arr+2)); printf("(pa+2)=%d\n",(pa+2)); } #include<stdio.h> int main() { int arr[5]={1,2,3,4,5}; //数组名表示的是一个地址 int *pa=arr; //数组元素的访问 printf("arr[0]=%d\n",arr[0]); //指针对数组元素的访问 printf("pa[0]=%d\n",pa[0]); printf("arr[4]=%d\n",arr[4]); printf("pa[4]=%d\n",pa[4]); } #include<stdio.h> int main() { char arr[16]={"hello,shanghai!"}; //数组名表示的是一个地址 char pc = arr; for(pc=arr;pc<arr+16;pc++) { if(pc>='a' && *pc<='z') *pc -= 32; } pc=arr; printf("%s\n",pc); }
(2) 野指针
没有初始化,或者其指向的内存被释放, 而指针没有被置空 危害:造成系统资源的浪费,容易造成未知的致命错误 #include<stdio.h> int main() { int num = 10; int pa = # printf("pa=%d\n",pa); int pb; //error ,未经初始化而使用,容易出现段错误 printf("pb = %d\n",pb); }
(3) 指针地址的运算
指针的自增和自减 自增:指针指向高地址方向 自减:指针指向低地值方向 #include<stdio.h> int main() { int arr[5]={1,2,3,4,5}; int *p = arr+3; printf("arr+3=%p\n",arr+3); printf("p=%p\n",p); p--; printf("p-- = %p\n",p); p++; printf("p++ = %p\n",p); } #include<stdio.h> int main() { int a=10; int b=34; int *pa=&a; int *pb=&b; //指针相减,表示两指针之间的距离 printf("pa-pb=%ld\n",pa-pb); //指针相加没有意义 printf("pa+pb=%ld\n",pa+pb); }
1、两个类型相同的指针相加毫无意义。比如p1和p2都是类型为int的指针,虽然他们指向的内存中保存了两个int数N1和N2,但是这两个数在内存中可能挨着,也可以能间隔很远,甚至有可能是一个地方。假设p1值也就是N1位置起始值为1234,P2为2345,这个时候如果直接相加得到的数据3589有可能已经超出了内存最大值或者指向某个无意义的内存地址,所以指针相加没有意义可言。正确的应该是N1和N2相加才是合理的算数运算。
2、指针可以相减,可以和立即数加或减,是有意义的,是允许的。比如我想知道N1和N2之间到底间隔了多少字节的内存,两者相减就相当于尺子上两个刻度相减,也就是长度或者宽度了。另外,和立即数的加减主来快速寻址,比如我有一个数组,起始指针为P0,如果数组保存的是一系列INT值那么 P0+2sizeof(int)得到的值就是第三个元素的所在位置的地址,也是一个指针,是有意义的(因为不同的语言和系统,int值每次所占的字节数可能不一致,所以使用sizeof函数去求得而不是直接加常规的4)。
(3) 指针加减一个常量,表示地址往高字节或底字节方向移动
常量值sizeof(对应数据类型)个字节 (4) 概念区分 int arr[3]; //数组大小为3,存放三个int型变量 int pb; //指针,棋类型为int 型 int arr[3]; //指针数组 具体是什么看后面的两个字 int (pa)[3]; //首先是指针 后是数组 所以是 数组指针,又称 行指针 #include<stdio.h> int main() { int arr[4]={1,2,3,4}; int buf[4]; int (pa)[4]; int i=0; for(i=0;i<4;i++) { buf[i]=&arr[i]; } pa=&arr; printf("%d\n",buf[2]); =3 printf("%d\n",(pa)[1]); =2 }
2.二级指针
DataType **PointorName; int a = 10; int *q = &a; int *p = &q; p=q; p=q=a; 定义一个指针, 或对地址进行操作时, 一定要确定指针的指向 #include<stdio.h> int main() { int a=10; int p=&a; int pa=&p; printf("&a=%p\n",&a); printf("p=%p\n",p); printf("&p=%p\n",&p); printf("pa=%p\n",&pa); printf("p=%d\n",p); printf("pa=%d\n",pa)
自我评价;今天讲的指针的基本的知识,以及指针数组,和数组指针的区别;脑子里有点懵,还是要多看多做,从最大程度上去理解它,掌握要领;大家要是有什么学习指针的方法,希望能够多提些建议,感谢不尽;要多花功夫啊学习这门语言的灵魂部分;