作業(yè)講解:
(1) 將2~100之間的素數(shù) 保存到數(shù)組中淹接,并遍歷輸出绵疲,每五行一個
#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整除的數(shù),
//若找到則跳出內(nèi)層循環(huán)
if(i%j==0)
break;
}
//若i==j,則i是素數(shù),否則不是
if(i==j)
{
arr[k]=i;
k++;
printf("%4d",i);
if(k%5==0)
printf("\n");
}
}
}
(2) 在一個升序或降序排列的數(shù)組中哗脖,插入一個元素;提示:數(shù)組元素部分初始化
(按升序或降序)至少空一個位置存放要插入的數(shù)據(jù)扳还。
插入元素后才避,仍然是按升序或降序排列
#include<stdio.h>
int main()
{
int arr[5]={10,9,12,8};
int i,j,k,temp;
printf("插入一個數(shù):\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)互換數(shù)
#include<stdio.h>
int main()
{
int arr[5];
int i,temp;
printf("請輸入五位數(shù):\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]);
}
一、數(shù)組
1氨距、二維數(shù)組
行數(shù)可以省略桑逝,列不可以省G稳谩楞遏!
#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};
//遍歷輸出二維數(shù)組
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");
}
}
求二維數(shù)組的總和余平均值
#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;
*:是指針的標(biāo)志
name: 變量名
指針和普通變量的區(qū)別:
指針:存地址
普通變量:存值
指針只能保存與其相同類型的地址
int *p; 只能保存int 型地址
char *pc; 只能保存char 型地址
double *pd; 只能保存double 型地址
(2) 指針初始化
int *p=NULL; //ok
int a=3; //ok
int *pa=&a;
int *pb; //ok
pb=&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:取指針對應(yīng)內(nèi)存里面的值
可以把指針變量賦值給同類型指針
#include<stdio.h>
int main()
{
int *p=NULL;
// printf("*p=%p\n",p);
//空地址不能訪問里面的值
// printf("*p=%d\n",p);//error內(nèi)存泄漏 核心轉(zhuǎn)儲
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);//內(nèi)存中并未分配0xa這塊內(nèi)存
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);
//強制類型轉(zhuǎn)化 臨時轉(zhuǎn)化 并不改變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 *));
}
結(jié)果:
sizeof(char *)=8
sizeof(short *)=8
sizeof(int *)=8
sizeof(long *)=8
sizeof(float *)=8
sizeof(double *)=8
(5) 指針的類型和指針?biāo)赶虻念愋?br>
int pa;
double pd;
指針的類型: 是類型+ 如 int *
指針?biāo)赶虻念愋?:就是類型 int
一句話就是指針的類型int 指向的是int類型
二、 指針與數(shù)組
(1) 數(shù)組名是一個地址
數(shù)組元素的訪問的方法:
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};
//數(shù)組名表示的是一個地址
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};
//數(shù)組名表示的是一個地址
int *pa=arr;
//數(shù)組元素的訪問
printf("arr[0]=%d\n",arr[0]);
//指針對數(shù)組元素的訪問
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!"};
//數(shù)組名表示的是一個地址
char *pc = arr;
for(pc=arr;pc<arr+16;pc++)
{
if(*pc>='a' && *pc<='z')
*pc -= 32;
}
pc=arr;
printf("%s\n",pc);
}
(2) 野指針
沒有初始化沙廉,或者其指向的內(nèi)存被釋放拘荡,
而指針沒有被置空
危害:造成系統(tǒng)資源的浪費,容易造成未知的致命錯誤
#include<stdio.h>
int main()
{
int num = 10;
int *pa = #
printf("*pa=%d\n",*pa);
int *pb;
//error ,未經(jīng)初始化而使用撬陵,容易出現(xiàn)段錯誤
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的指針,
雖然他們指向的內(nèi)存中保存了兩
個int數(shù)N1和N2粉臊,但是這兩個數(shù)在內(nèi)存中
可能挨著草添,也可以能間隔很遠,甚至有
可能是一個地方扼仲。假設(shè)p1值也就
是N1位置起始值為1234远寸,P2為2345抄淑,這個時候如果直接相加得到的數(shù)據(jù)
3589有可能已經(jīng)超出了內(nèi)存最大值或者指向某個無意義的內(nèi)存地址,所以
指針相加沒有意義可言驰后。正確的應(yīng)該是N1和N2相加才是合理的算數(shù)運算肆资。
2、指針可以相減灶芝,可以和立即數(shù)加或減郑原,是有意義的,是允許的夜涕。比如我想知道N1和N2之間到底間隔了多少字節(jié)的內(nèi)存犯犁,兩者相減就相當(dāng)于尺子上兩個刻度相減,也就是長度或者寬度了女器。另外酸役,和立即數(shù)的加減主來快速尋址,比如我有一個數(shù)組驾胆,起始指針為P0簇捍,如果數(shù)組保存的是一系列INT值那么 P0+2*sizeof(int)得到的值就是第三個元素的所在位置的地址,也是一個
指針俏拱,是有意義的(因為不同的語言和系統(tǒng)暑塑,int值每次所占的字節(jié)數(shù)可能不一致,
所以使用sizeof函數(shù)去求得而不是直接加常規(guī)的4)锅必。
(3) 指針加減一個常量事格,表示地址往高字節(jié)或底字節(jié)方向移動
常量值*sizeof(對應(yīng)數(shù)據(jù)類型)個字節(jié)
(4) 概念區(qū)分
int arr[3];
//數(shù)組大小為3,存放三個int型變量
int *pb;
//指針搞隐,棋類型為int *型
int *arr[3];
//指針數(shù)組 具體是什么看后面的兩個字
int (*pa)[3];
//首先是指針 后是數(shù)組 所以是
數(shù)組指針驹愚,又稱 行指針
#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;
定義一個指針,
或?qū)Φ刂愤M行操作時劣纲,
一定要確定指針的指向
#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);
}