7_1 指針的基本概念數組
_1.1 地址與指針 函數
C語言中一般把地址成爲指針。指針
_1.2 內存單元的指針與內存單元的內容code
_1.3 變量的指針對象
變量的指針就是變量的地址內存
_1.4 直接訪問與間接訪問字符串
7_2 指向變量的指針變量input
_2.1 指針變量的定義原型
形式:基類型說明符 *變量名 如:int *p1string
「*」也是一個說明符,p1是一個指針變量。
_2.2 指針變量的引用
1. 指針的專用運算符
(1) 取地址運算符& 例:&變量名
(2)指針運算符* 例:*變量名
2.指針變量的賦值
(1)指針變量的初始化
int a; int *ap=&a; /*定義指向總體變量a的指針變量ap*/
(2) 賦值語句:
①int *ap=&a,a; /*錯誤,不能把未定義的變量a的地址賦給ap*/ /*不容許把一個數賦予指針變量,被賦值的指針變量前也不能再加「*」說明符。*/ //②錯例: int *p; p=1000; /*不能把一個數賦予指針變量*/ *p=&a; /*被賦值的指針變量前不能再加「*」說明符*/
(3)將已被賦值的指針變量的值賦給另外一指針變量
int a,*ap,*bp; ap=&a; /*使指針變量ap指向變量a*/ bp=ap; /*將指針變量ap的值賦給指針變量bp;執行該語句後ap和bp都指向同一變量a*/
注:只有相同類型的指針變量之間能夠相互賦值。
錯例:
int a=3,*ap=&a; float bp; bp=ap; /*錯誤,指針變量bp只能指向float型變量(只能保存float型變量的地址)*/
(4) 能夠給指針變量賦0值如:
char *p=0;
該指針稱爲空指針,爲了程序的可讀性,一般符號常量NULL來表示空指針的值。如:
char *p=NULL;
3. 指針變量加減一個整數
一個指針加一個整數,表示將指針後移;相反,一個指針減一個整數,表示將指針前移。
4. 兩個同類指針變量相減
用於數組,差值表示兩個指針變量之間相隔的元素個數
5. 兩個同類指針變量做比較運算
用於判斷前後關係
6. 指針變量的引用舉例
【例7-1】 經過指針變量引用變量的值
#include<stdio.h> int main() { int a,b; int *ap,*bp; a=100; b=10; ap=&a; bp=&b; printf("%d,%d\n",a,b); printf("%d,%d\n",*ap,*bp); return 0; }
【例7-2】 指針變量及其簡單運算
#include<stdio.h> int main() { int x=3,y,*xp=&x; y=*xp+5; printf("y=%d\n",y); y=++*xp; printf("%d\n",y); y=*xp++; printf("x=%d,y=%d\n",x,y); /*表示把x的值賦給y再使xp後移,即等價於y=*xp;xp++;*/ return 0; }
注:「++」和「*」的運算優先級相同且都是自右向左。
_2.2 指針變量做爲函數參數
【例7-3】 用通常變量做爲參數,不能實現交換。
#include<stdio.h> int main() { int swap(int x,int y); int a=100,b=10; printf("%d,%d\n",a,b); swap(a,b); printf("%d,%d\n",a,b); return 0; } int swap(int x,int y) /*交換指針變量ap,bp所指向是地址單元中的內存*/ { int temp; temp=x; x=y; y=temp; }
【例7-4】若改寫爲指針函數爲參數便可交換。
#include<stdio.h> int main() { int swap(int *ap,int *bp); int a=100,b=10; printf("%d,%d\n",a,b); swap(&a,&b); printf("%d,%d\n",a,b); return 0; } int swap(int *ap,int *bp) /*交換指針變量ap,bp所指向是地址單元中的內存*/ { int temp; temp=*ap; *ap=*bp; *bp=temp; }
7_3指針與數組
_3.1 指針與一維數組
1. 指向數組元素的指針變量
形式:基類型說明符 *指針變量 如:
int a[10]; int *p; p=&a[0];
C語言規定,把數組的首地址稱爲數組的指針。
(1)p、a、&a[0]均指向同一單元,它們是數組a的首地址,可是p是指針變量,而a、&a[0]都是指針常量。
2. 經過指針引用數組元素
三種方法:①下標法 ②常量指針法 ③指針變量法。
(1)下標法
#include<stdio.h> int main() { int a[5],i; printf("Please input 5 numbers:"); for (i=0;i<5;i++) scanf("%d",&a[i]); for (i=0;i<5;i++) printf("a[%d]=%-4d",i,a[i]); printf("\n"); return 0; }
(2)常量指針法:
#include<stdio.h> int main() { int a[5],i; printf("Please input 5 numbers:"); for (i=0;i<5;i++) scanf("%d",a+i); for (i=0;i<5;i++) printf("a[%d]=%-4d",i,*(a+i)); printf("\n"); return 0; }
(3)指針變量法:
#include<stdio.h> int main() { int a[5],i,*p=a; printf("Please input 5 numbers:"); for (i=0;i<5;i++) scanf("%d",p+i); for (i=0;i<5;i++) printf("a[%d]=%-4d",i,*(p+i)); printf("\n"); return 0; }
(4)指針帶下標法:
#include<stdio.h> int main() { int a[5],i,*p=a; printf("Please input 5 numbers:"); for (i=0;i<5;i++) scanf("%d",&p[i]); for (i=0;i<5;i++) printf("a[%d]=%-4d",i,p[i]); printf("\n"); return 0; }
(5)逐個移動指針法:
#include<stdio.h> int main() { int a[5],i,*p=a; printf("Please input 5 numbers:"); for (i=0;i<5;i++) scanf("%d",p++); p=a; for (i=0;i<5;i++) printf("a[%d]=%-4d",i,*p++); printf("\n"); return 0; }
3.用數組的指針做爲函數的參數
【例7-7】用冒泡法對10個整數按升序排列
#include<stdio.h> #define N 5 int main() { void output(int *p,int n); void sort (int x[],int n); int a[N],i,*p; printf("請輸入%d個整數:\n",N); for (i=0;i<N;i++) scanf("%d",&a[i]); printf("\n"); printf("原數組以下:\n"); output (a,N); p=a; sort (p,N); printf("升序結果以下:\n"); output (a,N); return 0; } void output (int *p,int n) { int i; for(i=0;i<n;i++) printf("%-4d",*(p+i)); printf("\n"); } void sort (int x[],int n) { int i,j,k,t; for(i=0;i<n-1;i++) { for (j=0;j<n-i-1;j++) if (x[j]>x[j+1]) {t=x[j];x[j]=x[j+1];x[j+1]=t;} } }
_3.2 指針與多維數組
1.多維數組的地址
2.指向二維數組元素的指針變量
【例7-9】用指針變量輸入多維數組的值
#include<stdio.h> int main() { int a[2][3]={{1,2,3},{4,5,6}},i; int *p=a[0]; for (i=0;i<6;i++) { printf("%-4d",p[i]); if ((i+1)%3==0) printf("\n"); } return 0; }
3.指向一維數組的指針變量
形式:類型說明符 (*指針變量名)[長度];如:
int (*p)[3];
【例7-10】用指向一維數組的指針變量輸出二維數組中的各元素值。
#include<stdio.h> int main() { int a[2][3]={1,2,3,4,5,6}; int *(p)[3]; int i,j; for (i=0;i<2;i++) { for (j=0;j<3;j++) printf("%-4d",*(*(p+i)+j)); printf("\n"); } return 0; }
7_4 字符串與指針
_4.1 字符指針的定義與引用
對指向字符變量的指針變量應賦予該字符變量的地址。如:
char c,*p=&c;
對指向字符串的指針變量應賦予一個字符串的首地址,如:
char c,*p="China";
等效於:char *p; p="China";
【例7-11】用字符指針處理字符數組中的字符串
#include<stdio.h> int main() { char s[]="China"; char *p=s; while (*p!='\0') { putchar(*p); p++; } printf("\n"); return 0; }
【例7-12】用字符指針處理字符串
#include<stdio.h> int main() { char s[]="China"; char *p=s; printf("%s\n",p); return 0; }
_4.2 字符指針做爲函數參數
【例7-14】對字符串內容做修改
#include<stdio.h> void change (char *s) { s[2]='r'; } int main() { char a[]="file"; change (a); printf("%s\n",a); return 0; }
7_5 指針數組
_5.1 用指針數組處理二維數組
【例7-15】 用指針數組處理二維數組
#include<stdio.h> int main() { int a[2][3]={{1,2,3},{4,5,6}},i,j; int *pa[2]; /*定義數組pa,它的兩個數組pa[0]和pa[1]都是存放指針變量的*/ pa[0]=a[0]; pa[1]=a[1]; for (i=0;i<2;i++) { for (j=0;j<3;j++) printf("%-4d",*(pa[i]+j)); printf("\n"); } return 0; }
_5.2 用字符指針數組處理一組字符串
【例7-16】 用冒泡法對字符按字母順序升序排列
#include<stdio.h> #include<string.h> void sort (char *a[],int n) { int i,j; char *t; for (i=0;i<n-1;i++) for (j=0;j<n-i-1;j++) if (strcmp (a[j],a[j+1])>0) {t=a[j];a[j]=a[j+1];a[j+1]=t;} } int main() { char *p[5]={"Basic","Pascal","Fortran","C","Java"}; int i; sort (p,5); for(i=0;i<5;i++) printf("%s\n",p[i]); return 0; }
7_6 指向指針的指針
二級指針的定義格式: 類型說明符 **指針變量名; 如:
int **p;
#include<stdio.h> int main() { char *pa[5]={"Basic","Pascal","Fortran","C","Java"}; char **p; p=pa; while (pa<pa+5) { printf("%s\n",*p); p++; } return 0; }
7_7 指針與函數
_7.1 指針型函數
指針型函數:返回指針值的函數
形式:類型說明符 *函數名(形參表列)
{
…… /*函數體*/
}
【例7-18】輸入一個1~7之間的函數,輸出對應星期名的英語單詞。
#include<stdio.h> char *day_name(int n) { char *name[]={"Monday ","Tuseday","Wednesday","Thursday","Friday","Saturday","Sunday"}; return (name[n-1]); } int main() { int i; char *day_name(int n); printf("\t星期名對應的英文單詞查詢\n請輸入一個1~7之間的整數:"); scanf("%d",&i); while (i<1||i>7) { printf("出錯!,請從新輸入:"); scanf("%d",&i); } printf("星期%d對應的英語單詞:%s\n",i,day_name(i)); return 0; }
_7.2 指向函數的指針變量
格式:類型說明符 (*指針變量名)();如:
int (*p)();
【例7-19】 求兩數較大者
#include<stdio.h> int max(int a,int b) { if(a>b) return a; else return b; } int main() { int x,y,z; int (*p)(); p=max; printf("請輸入兩個整數(用逗號分隔):\n"); scanf("%d,%d",&x,&y); z=(*p)(x,y); printf("兩數中較大者爲:%d\n",z); return 0; }
7_8 指針應用過程當中的注意事項
1. 要準確理解指針的含義,區別指針和指針變量的不一樣含義。
2. 在對數組進行操做時,要能正確的使用指針。
3. 讀者須對各類有關的指針變量定義形式加深理解。
4. void指針,即「指向空類型的指針」,是指不指向具體數據對象的指針。
5. 指針還能夠實現對動態分配的內存空間進行有效的管理。
C語言中,經常使用malloc()和free()這兩個函數以及sizeof運算符動態分配和釋放內存空間。
malloc()函數和free()函數所需的信息一般在頭文件stdio.h 中,其函數原型及功能以下:
(1)malloc()函數
函數原型:
void *malloc (unsigned size)
功能:從內存分配一個大小爲size個字節的內存空間。若是分配成功,返回新分配內存的首地址;若是沒有足夠的內存分配,則返回NULL。
爲確保內存分配準確,函數malloc()一般和運算符sizeof 一塊兒使用。例:
int *p; p=(int* )malloc(20*sizeof(int));/*分配20個所需的內存空間*/
(2) free函數
函數原型:void free(void *p);
功能:釋放由指針變量p所指向的內存塊,無返回值。如:
int *p; p=(int* )malloc(20*sizeof(int));/*分配20個所需的內存空間*/ …… free(p);
【例7-20】 輸入n名學生的C語言成績,並將這些成績逆序輸出。
#include<stdio.h> int main() { float *score; int n,i; printf("請輸入學生人數:"); scanf("%d",&n); score=(float*)malloc(n*sizeof(float)); if(!score) printf("分配空間失敗!\n"); else { printf("請輸入%d個學生的成績(空格分隔):\n",n); for (i=0;i<n;i++) scanf("%f",score+i); printf("逆向輸出各成績以下:\n"); for (i=n-1;i>=0;i--) printf("%7.2f",score[i]); printf("\n"); free(score); } return 0; }