C 指針
理解指針定義 --存放地址
內存區的每一個字節有一個編號, 這就是“地址”。 如果在程序中定義了一個變量, 在對程序進行編譯
時, 系統就會給這個變量分配內存單元。
在c程序裏面有兩種訪問方式: 1. 是直接訪問, 2是間接訪問(a的箱子要是在b抽屜裏)。
直接訪問: a=5;, 系統在編譯是,已經對變量分配了地址 如果變量的a的地址是2000, 那麽這個語句的作用就是 把常數5保存到地址為2000的單元。
間接訪問如:scanf(“%d”, &a); 調用函數時, 把變量a的地址傳遞給函數scanf, 函數首先把該地址保存到一個單元中, 然後把鍵盤接受的數據通過所存儲的地址保存到a的變量中。
定義指針
int i=5;
int * i_abc; 定義指針變量 i_abc = & i; 存放整型變量i的地址
深入理解:
將i 的內存地址2000存放到i_abc,這時, i_abc的值就是(2000, i的內存地址),即變量i所占用單元
的起始地址。要存取變量i的值,可以采取間接方式:先找到存放“i的地址”的變量i_abc, 然後從中取出i的地址(2000)
然後取出i的值3.
代碼講解
* : 叫取值操作符
&: 叫取址操作符
int i = 5; int *abc; // 這個*不是取值操作符,而是聲明他是指針變量, 也就是定義指針變量 abc= &i; // 存放指針,也就是內存地址 &i 的地址是2000 printf("%d\n", *abc);//這個才是取值操作符, 加上*系統知道他是指針的值
註意:
定義的時候:
float a; int *abc; abc = &a; 這樣是錯誤的,關系到取址, 比如有浮點是8位,而整型是4位,那就會少4位
說明:
如果已執行了語句 abc = &a;
1) . &*abc的含義是什麽?
"&"和 "*" 兩個運算符的優先級相同, 但按照自右而左方向結合, 因此先進行*abc 的運算, 他就是變量a,
例如: printf("%d\n", *abc);
再執行&運算。
2)。 * & a的含義是蛇年意思?
先&a運算,然後在×運算, 最後還是指向a
針對數組的指針 ---------------------------
p= &a【0】 // 把a【0】元素的地址賦給指針變量p
註意一個小地方:
引用一個數組元素, 可以用:
1)。下標法, 如a【i】形式; 2)。指針法, 如*(a+i) 或(p+1) 其中的a是數組名, p是指向數組元素的指針變量, 其初值p=a。也就是 a指向的數組第一個值 數組名即“翻譯成數組的第一個元素地址”
要輸出數組中的全部元素的三種方法-------一維數組
方法1:下標法
#include <stdio.h> int main(int argc, char const *argv[]) { /* code */ int a[10]; int i; for(i = 0; i < 10; i++) { scanf("%d", &a[i] ); } for(i=0;i<10;i++) { printf("%d\n", a[i]); } return 0; }
方法2: 通過數組名計算數組元素的地址, 找出元素值
#include <stdio.h> int main(int argc, char const *argv[]) { /* code */ int a[10]; int i; for(i = 0; i < 10; i++) { scanf("%d", &a[i] ); } for(i=0;i<10;i++) { printf("%d\n", *(a+i)); } return 0; }
方法3:用指針變量指向數組元素
#include <stdio.h> int main(int argc, char const *argv[]) { int a[10]; int i; int *p; for (i=0;i<10;i++) { scanf("%d", &a[i]); } for (p = a; p < (a+10); p++) { /* code */ printf("%d", *p); } return 0; }
用數組名作為函數參數--------------------------------------------
f(int a[], int n) 但在編譯時是將arr按指針變量處理的, 相當於將函數f的首部寫成f(int *arr, int n) 等價的
看試題:
要求將數組a中n個整數按相反順序存放
#include <stdio.h> int main(int argc, char const *argv[]) { void reverse(int *x, int); int i, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2}; for (i = 0; i < 10; i++) { printf("%d", a[i]); } printf("\n"); reverse(a, 10); for (i = 0; i < 10; i++) { printf("%d", a[i]); } printf("\n"); return 0; } void reverse(int x[], int n) { int temp, i, j, m; m = (n-1)/2; for (i = 0; i <= m; i++) { j = n-1-i; temp = x[i]; x[i] = x[j]; x[j] = temp; } }View Code
指針寫法
#include <stdio.h> int main(int argc, char const *argv[]) { void reverse(int *x, int); int i, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2}; for (i = 0; i < 10; i++) { printf("%d", a[i]); } printf("\n"); reverse(a, 10); for (i = 0; i < 10; i++) { printf("%d", a[i]); } printf("\n"); return 0; } void reverse(int *x, int n) { int *p, temp, *i, *j, m; m = (n - 1)/2; i = x; j = x + n -1; p = x + m; for (;i <= p;i++, j--) { temp = *i; *i = *j; *j = temp; } }View Code
二維數組
內存地址
怎麽用指針尋找的規律
從前面的圖可以分析得出結論 *(p+i) + j 是二維數組i行j列的元素地址
而*(*(p+i) +j) 則是i行j列的值
定義多維數組元素的指針變量
把二維數組a分解為一維數組a[0], a[1], a[2]之後, 設p為指向二維數組的指針變量
可定義為:
int (*p)[4]
表示p是一個指針變量, 他指向包含4個元素的一維數組。 若指向第一個一維數組a[0], 其值等於a,
a【0】, 或&a【0】【0】等。
#include <stdio.h> int main(int argc, char const *argv[]) { int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11}; int (*p)[4]; int i, j; p = a; for (i=0; i < 3; i++) { /* code */ for (j = 0;j<4;j++) { // printf("%2d", *(*p+i)+j); //註意這個錯誤,是我當初犯下的錯誤 printf("%2d", *(*(p+i)+j)); } printf("\n"); } return 0; }
字符串與指針 --------------------------------------
用數組的形式來表示字符串
#include <stdio.h> int main(int argc, char const *argv[]) { char string[] = "I love you , Future girl" ; printf("%s\n", string); return 0; }
用指針的形式
#include <stdio.h> int main(int argc, char const *argv[]) { char *string = "I love you , Future girl" ; printf("%s\n", string); return 0; }
對字符串中的字符的存取方法有兩種
1. 是下標法:
#include <stdio.h> int main(int argc, char const *argv[]) { char a[] = "hahhahahaha, future girl", b[40]; int i; for (i = 0; *(a + i) != ‘\0‘; i++) { *(b + i) = a[i]; } *(b + i) = ‘\0‘; printf("%s\n", a); printf("%c\n", *a); for (i = 0; b[i] != ‘\0‘; i++) { printf("%c", b[i]); } printf("\n"); return 0; }View Code
2.是指針方法:
#include <stdio.h> int main(int argc, char const *argv[]) { char a[] = "hahhahahaha, future girl", b[40], *p1, *p2; int i; p1 = a; p2 = b; for (; *p1 != ‘\0‘; p1++, p2++) { *p2 = *p1; } *p2 = ‘\0‘; printf("wo shi a:%s\n", a); for (i = 0; b[i] != ‘\0‘; i++) { printf("%c", b[i]); } return 0; }View Code
字符指針作函數參數以及指針a【】和*a 的區別 -----------------------------
*a 是不可寫的,a【】是可寫的
為什麽: char *a = "i am a;"; 是放常量的,常量是不可寫的。
在c/c++中,內存分為5個區, 堆,棧, 自由存儲區, 全局/靜態存儲區和常亮存儲區。
方法一:用字符串數組作參數
#include <stdio.h> int main(int argc, char const *argv[]) { int copy_str(char from[], char to[]); char a[] = "i am a;"; char b[] = "i am b;"; printf("%s\n%s\n----------------\n", a, b); copy_str(a, b); printf("%s\n%s\n", a, b); return 0; } int copy_str(char from[], char to[]) { int i = 0; while (from[i] != ‘\0‘) { to[i] = from[i]; i++; } to[i] = ‘\0‘; return 0; }View Code
方法二: 形參用字符指針變量
#include <stdio.h> int main(int argc, char const *argv[]) { int copy_str(char *from, char *to); char *a = "i am a;"; char b[] = "i am b;"; //註意這是b是不是為×b,否則報錯不能寫入 printf("%s\n%s\n----------------\n", a, b); copy_str(a, b); printf("%s\n%s\n", a, b); return 0; } int copy_str(char *from, char *to) { for (; *from != ‘\0‘; from++, to++) { *to = *from ; } return 0; }View Code
還有一種巧妙方法
#include <stdio.h> int main(int argc, char const *argv[]) { int max(int, int); int (*p)(); int a, b, c; p = max; scanf("%d %d", &a, &b ); c = (*p)(a, b); //關鍵是這句 printf("%d, %d\n", a, b); printf("%d\n", c); return 0; } int max(int x, int y) { int z; if (x > y) { z = x; } else { z = y; } return z; }View Code
C 指針