2.2 指標的計算
阿新 • • 發佈:2019-01-09
1. 1 + 1 = 2?
給一個指標 加 1,表示要讓指標指向下一個變數
如果指標不是指向一片連續分配的空間,這種運算沒有意義
#include<stdio.h>
int main(void)
{
// char 陣列
char ac[] = {0, 1, 2, 3, 4, 5, 6};
char *p = ac;
printf("p=%p\n", p); // p=000000000022FE40
printf("P+1=%p\n", p + 1); // P+1=000000000022FE41
printf("sizeof(char)=%d\n", sizeof(char )); // sizeof(char)=1
// int 陣列
int ai[] = {1, 2, 3, 4, 5};
int *q = ai;
printf("q=%p\n", q); // q=000000000022FE10
printf("q+1=%p\n", q + 1); // q+1=000000000022FE14
printf("sizeof(int)=%d\n", sizeof(int)); // sizeof(int)=4
printf("*(q+1)=%d\n", *(q + 1)); // *(q+1)=2 即 *(q + 1) = ai[1]
return 0;
}
2. 指標的算術運算
可以給指標 加 減一個整數、遞增(++)、遞減(–)、兩個指標相減
#include<stdio.h>
int main(void)
{
char ac[] = {0, 1, 2, 3, 4, 5, 6, 7};
char *p = &ac[0];
char *p1 = &ac[5];
printf("p =%p\n", p); // p =000000000022FE20
printf("p+1=%p\n", p + 1); // p+1=000000000022FE21
printf("p1-p=%d\n", p1-p); // p1-p=5
int ai[] = {1, 2, 3, 4, 5, 6, 7, 8};
int *q = ai;
int *q6 = &ai[6];
printf("q =%p\n", q); // q =000000000022FE20
printf("q6=%p\n", q6); // q6=000000000022FE38,十六進位制
printf("q6-q=%d\n", q6-q); // q6-q=6
return 0;
}
3. *p++
- 先計算 ++,在計算 *
- 取出 p 所指的那個資料,再將p移到下一個位置
- 用於陣列類的連續空間操作
- 在某些CPU上,可以直接被翻譯成一條彙編指令
#include<stdio.h>
int main(void)
{
char ac[] = {0, 1, 2, 3, 4, 5, 6, -1};
char *p = &ac[0];
int i;
for(i = 0; i < sizeof(ac)/sizeof(ac[0]); i++){
printf("%d\n", ac[i]);
}
printf("-------------\n");
// 假設 -1 表示結束
while( *p != -1){
printf("%d\n", *p++);
}
return 0;
}
4. 指標比較
<, <=, == , >, >=, != 都可以對指標做
可以比較在記憶體中的地址
陣列中的單元的地址肯定是 現行遞增的
5. 0地址
- 0地址通常是不能隨便碰的地址,所以你的指標不應該具有 0值
- 可以用0地址來表示特殊的事:
- 返回的指標是無效的
- 指標沒有被真正初始化
- NULL是一個預定義的符號,表示0地址
- 有的編譯器不願意用0來表示0地址
6.指標的型別
- 無論指向什麼型別,所有的指標的大小都是一樣的,因為都是地址
- 指向不同型別的指標 不能直接互相賦值,這是為了避免用錯指標
#include<stdio.h>
int main(void)
{
char ac[] = {0, 1, 2, 3, 4, 5, 6, -1};
char *p = &ac[0];
int ai[] = {0, 1, 2, 3, 4, 5, 6};
int *q = ai;
// q = p; // [Error] cannot convert 'char*' to 'int*' in assignment
return 0;
}
7. 指標的型別轉換
- void* 表示不知道指向什麼東西的指標
- 指標也可以轉換型別
#include<stdio.h>
int main(void)
{
int i = 5;
int *p = &i;
// 沒有改變p所指的變數的型別,只是換了個看待p所指變數的方式
// 不再當它是 int,認為是 void
void* q = (void*)p;
return 0;
}
8.指標的用途
- 需要傳入比較大的資料時 用作引數
- 傳入陣列後,對陣列做操作
- 函式返回不止一個結果,需要用函式來修改不止一個變數
- 動態申請的記憶體
9. 動態分配記憶體
9.1 malloc
#include<stdlib.h>
void* malloc(size_t size);
- malloc申請的空間的大小是以位元組為單位的
- 返回的型別是 void*,需要型別轉換為 自己需要的型別,比如 (int*)malloc(n * sizeof(int))
- 如果什麼失敗則返回0,或者叫做NULL
輸入資料時,先告訴你個數n,再輸入n個數字,要記錄每個資料
C99可以用變數n做陣列定義的大小,C99之前呢?用 int a = (int )malloc(n * sizeof(int));
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int number;
int* a;
printf("輸入數量:");
scanf("%d", &number);
a = (int*)malloc(number * sizeof(int));
int i;
for(i = 0; i < number; i++){
scanf("%d", &a[i]);
}
for(i = number - 1; i >= 0; i--){
printf("%d ", a[i]);
}
free(a);
return 0;
}
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
//你的系統能給你多大空間?
void *p;
int cnt = 0;
while((p=malloc(100 * 1024 * 1024))) {
cnt++;
}
printf("分配了%d00MB的空間\n", cnt); // 分配了10300MB的空間
return 0;
}
9.2 free
- 把申請得來的空間還給系統
- 只能還申請來的空間的首地址
常見問題
- 申請了沒free,長時間執行記憶體逐漸下降
- 新手:忘了
- 老手:找不到合適的free的時機
- free過了再free
- 地址變了,直接去free