》》每個內存單元只能同時存儲一個數據,如何保證內存單元同時只能存儲一個數據,可使用編號的方式實現內存單元標記,此編號就是指針。小程序
》》指針是一個變量,指針是存放着一個數據的內存地址而不是數據自己的值,其是查找數據的另外一種方式數組
【&】在變量中取地址函數
【*】在地址中取變量測試
測試小程序:spa
#include<stdio.h> void main() { int i = 10;//定義一個變量,並賦初始值爲10 int *p = &i;//定義一個指針變量,並賦初始值爲i的地址 *p = 199; printf("%d=%d", *p,i);//輸出199=199 printf("---%d---", p);//獲得變量i的地址 }
》》指針類型:int *、float*、long*、double*、char*等等3d
》》指針變量的類型須要與存儲的數據類型相同指針
》》肯定類型能夠方便指針變量肯定存儲數據的大小,爲數據尋找到結束符,如int類型佔四個字節、char佔一個字節。也方便指針使用加1或減1操做,如int加減1會跳動4個字節,char加減1會跳動兩個字節。code
int i=10; int *p=&i;blog
int *pp;ip
pp=p;
指針運算符:
*p++
等同於*(p++),運算優先級爲從右到左,應該是先*p取值,而後地址移動一位,要區別與*(++p)。
#include<stdio.h> //int *a1=&b1; void fun(int *a1, int* a2) { *a1 = 100; int ii = 99; a2 = ⅈ//讓指針從新指向另一個地址 printf("獲得的數據:%d,%d", *a1, *a2);//輸出100,99 } void main() { int b1 = 1, b2 = 2; fun(&b1, &b2); printf("調用函數後:%d,%d", b1, b2);//輸出100,2 }
輸出b2的結果並非相同的值,是由於執行調用函數改變了實參指針變量的值,並非改變了實參指針變量所指變量的值
數組名(如arr)表明元素的首地址,數組第一個元素的地址也是這個數組的首地址(如&arr[0])。
數組指針中使用加減1將跳到下一個或者上一個數組元素地址,與使用 &arr[n+1] 基本相同。
若是整數數組名爲arr,運行int *p=arr,則*(p+3)、p[3]、*(arr+3)、arr[3]效果均是取出數組arr的第三個元素,在編譯時arr[3]其實是*(arr+3)處理的。
#include<stdio.h> void main() { int arr[] = { 5,4,3,2,0 }; int *p = arr; int *pp = &arr[0]; printf("%d", *(p+3));//輸出2 }
函數數組參數
#include<stdio.h> //等價於void fun(char a1[]) { void fun(char *a1) { *(a1 + 2) = 'c';//改變第二個值的內容 } void main() { char b1[] = { "123456789" }; fun(b1); printf("調用函數後:%s", b1);//輸出: 12c456789 }
#include<stdio.h> void main() { int a1[][3] = { {10,11,12},{100,110,120} }; int a[][3] = { 10,11,12,100,110,120 }; printf("地址:%d==%d==%d==%d", a[0], &a[0][0],*(a+0),a+0);//輸出地址 printf("%d===%d==%d", a[0][1], *(*(a + 0)+1),*(a[0]+1));//獲得值 }
字符串常量【char *ch = "dong xiao dong";】表示其指向地址的內容不可變,但指向的地址是可變的;
字符串變量【char ch[] = "dong xiao dong";】其指向地址的內容可變。
#include<stdio.h> void main() { //char *ch = "dong xiao dong"; //字符串常量,不可變 char ch[] = "dong xiao dong"; //字符數組,可變 ch[2] = '2';//字符串常量運行這條將報錯 printf("%s\n", ch); }
可變格式的輸出函數:
#include<stdio.h> void main() { char *ch = "dong xiao %d\n"; printf(ch, 10); ch = "xiaoxiao%d\n"; printf(ch, 10); char chh[] = "dongdong %d\n"; printf(ch, 100); }
【int(*p)(int, int);//定義一個函數指針變量p】,第一個int表示返回值類型,第二個int和第三個int表示函數的參數類型。注意*p兩側的括號不能省略,表示p先與*結合,是指針變量,而後再於後面的()結合,()表示是函數,即該指針變量不是指向通常的變量,而是指向函數。若是寫成「int * p(int,int);」,因爲()優先級高於*,它至關於「int *(p(int,int))」,就成了聲明一個p函數,而且這個函數的返回值是指向整型變量的指針。
返回值爲int
#include<stdio.h> void main() { int minto(int a, int b);//函數聲明 int(*p)(int, int);//定義一個函數指針變量p p = minto;//函數指針指向函數minto首地址 int cc = (*p)(11, 55);//調用函數 printf("Min===%d", cc); } int minto(int a, int b) { if(a > b) return b; else return a; }
無返回值:
#include<stdio.h> void main() { void fun(int a);//函數聲明 void (*p)(int);//定義一個函數指針變量p p = fun;//函數指針指向函數fun首地址 (*p)(11);//調用函數 } void fun(int a) { printf("%d\n", a); }
指向函數指針做爲函數的參數
#include<stdio.h> void main() { int fun(int(*addpp)(int, int), int x, int y);//函數聲明 int add(int i, int j); int ii=fun(add, 11, 12);//傳遞函數名和參數便可 printf("輸出相加的值爲:%d", ii); } //int (*addpp)(int,int);addpp=add; int fun(int (*addpp)(int,int),int x,int y){ int cc = (*addpp)(x, y); return cc; } int add(int i, int j) { return i + j; }
#include<stdio.h> void main() { int* add(int i, int j); int *p = add(10, 4); printf("輸出相加的值爲:%d", *p); } int* add(int i, int j) { int aa = i + j; return &aa;//返回地址 }
一個數組其所有元素都存放着指針,就是指針數組【int * p[5];】
#include<stdio.h> void main() { //指針數組 char * p[] = { "dong1","xiao2","dong3","dong4" }; printf("%s\n", p[2]); }
進階版
#include<stdio.h> void main() { //指針數組(字符串) char * p[] = { "dong1","xiao2","dong3","dong4" }; char **pp; pp = p; printf("%s\n", *(pp+1));//轉換一次就能夠拿到對應字符串的首地址經過%s打印 //指針數組(整數) int a[5]= {10,11,12,13 }; int * ip[] = { &a[0],&a[1],&a[2],&a[3],&a[4]}; int **ppp = ip; printf("%d\n", *(*ppp+1));//轉換第一次獲得存儲的指針,再次轉換獲得值 }
一、
int *p=10; //等同於:int *p; p=10;
分析:非法操做,內存地址不能用戶自定義。10至關於一個內存地址,該內存地址的值不肯定且也不明確該地址是否能夠直接訪問,正確的應該是使用【&變量名】獲得內存地址。
二、
int f = 12.3; int *p; *p = &f; //錯誤1 int ff = &f; //錯誤2
分析:指針(地址)必須賦值給指針變量