指針和記憶體單元
指針: 位址。
記憶體單元: 計算機中記憶體最小的存儲機關。——記憶體單元。大小一個位元組。 每一個記憶體單元都有一個唯一的編号(數)。
稱這個記憶體單元的編号為 “位址”。
指針變量:存位址的變量。
指針定義和使用:
int a = 10;
int *p = &a; int* p;--- windows; int *p ---Linux int * p ;
int a, *p, *q, b;
*p = 250; 指針的 解引用。 間接引用。
*p : 将p變量的内容取出,當成位址看待,找到該位址對應的記憶體空間。
如果做左值: 存資料到空間中。
如果做右值: 取出空間中的内容。
任意“指針”類型大小:
指針的大小與類型 無關。 隻與目前使用的平台架構有關。 32位:4位元組。 64位: 8位元組。
using namespace std;
int main() {
int a=10;
int *p = &a;
printf("指針位址%d\n",p);
printf("存指針位址:%d\n",&p);
printf("解引用:%d\n",*p);
printf("a的位址%d\n",&a);
return 0;
}
野指針:
1) 沒有一個有效的位址空間的指針。
int *p;
*p = 1000;
2)p變量有一個值,但該值不是可通路的記憶體區域。
int *p = 10;
*p = 2000;
【杜絕野指針】
空指針:
int *p = NULL; #define NULL ((void *)0)
*p 時 p所對應的存儲空間一定是一個 無效的通路區域。
萬能指針/泛型指針(void *):
可以接收任意一種變量位址。但是,在使用【必須】借助“強轉”具體化資料類型。
char ch = 'R';
void *p; // 萬能指針、泛型指針
p = &ch;
printf("%c\n", *(char *)p);
const關鍵字:
修飾變量:
const int a = 20;
int *p = &a;
*p = 650;
printf("%d\n", a);
修飾指針:
const int *p;
可以修改 p
不可以修改 *p。
int const *p;
同上。
int * const p;
可以修改 *p
不可以修改 p。
const int *const p;
不可以修改 p。
不可以修改 *p。
總結:const 向右修飾,被修飾的部分即為隻讀。
常用:在函數形參内,用來限制指針所對應的記憶體空間為隻讀。
指針和數組:
數組名:
【數組名是位址常量】 --- 不可以被指派。 ++ / -- / += / -= / %= / /= (帶有副作用的運算符)
指針是變量。可以用數組名給指針指派。 ++ --
取數組元素:
int arr[] = {1,3, 5, 7, 8};
int *p = arr;
arr[i] == *(arr+0) == p[0] == *(p+0)
指針和數組差別:
1. 指針是變量。數組名為常量。
2. sizeof(指針) ===》 4位元組 / 8位元組
sizeof(數組) ===》 數組的實際位元組數。
指針++ 操作數組:
int arr[] = { 1, 2, 4, 5, 6, 7, 8, 9, 0 };
int *p = arr;
for (size_t i = 0; i < n; i++)
{
printf("%d ", *p);
p++; // p = p+1; 一次加過一個int大小。 一個元素。
}
p的值會随着循環不斷變化。列印結束後,p指向一塊無效位址空間(野指針)。
指針加減運算:
資料類型對指針的作用:
1)間接引用:
決定了從指針存儲的位址開始,向後讀取的位元組數。 (與指針本身存儲空間無關。)
2)加減運算:
決定了指針進行 +1/-1 操作向後加過的 位元組數。
指針 * / % : error!!!
指針 +- 整數:
1) 普通指針變量+-整數
char *p; 列印 p 、 p+1 偏過 1 位元組。
short*p; 列印 p 、 p+1 偏過 2 位元組。
int *p; 列印 p 、 p+1 偏過 4 位元組。
2)在數組中+- 整數
short arr[] = {1, 3, 5, 8};
int *p = arr;
p+3; // 向右(後)偏過 3 個元素
p-2; // 向前(左)偏過 2 個元素
3)&數組名 + 1
加過一個 數組的大小(數組元素個數 x sizeof(數組元素類型))
指針 +- 指針:
指針 + 指針: error!!!
指針 - 指針:
1) 普通變量來說, 文法允許。無實際意義。【了解】
2) 數組來說:偏移過的元素個數。
#include <iostream>
using namespace std;
int main() {
int a[]= {3,2};
int *p = a;
printf("指針位址%d\n",p);
printf("存指針位址:%d\n",&(p));
printf("解引用:%d\n",*p);
printf("a的位址%d\n",&a);
printf("存指針位址:%d\n",*(p+1));
return 0;
}
指針實作 strlen 函數:
char str[] = “hello”;
char *p = str;
while (*p != ‘\0’)
{
p++;
}
p-str; 即為 數組有效元素的個數。
指針比較運算:
1) 普通變量來說, 文法允許。無實際意義。
2) 數組來說: 位址之間可以進行比較大小。
可以得到,元素存儲的先後順序。
3) int *p;
p = NULL; // 這兩行等價于: int *p = NULL;
if (p != NULL)
printf(" p is not NULL");
else
printf(" p is NULL");
指針數組:
一個存儲位址的數組。數組内部所有元素都是位址。
1)
int a = 10;
int b = 20;
int c = 30;
int *arr[] = {&a, &b, &c}; // 數組元素為 整型變量 位址
2)
int a[] = { 10 };
int b[] = { 20 };
int c[] = { 30 };
int *arr[] = { a, b, c }; // 數組元素為 數組 位址。
指針數組本質,是一個二級指針。
二維數組, 也是一個二級指針。
多級指針:
int a = 0;
int *p = &a; 一級指針是 變量的位址。
int **pp = &p; 二級指針是 一級指針的位址。
int ***ppp = &pp; 三級指針是 二級指針的位址。
int ****pppp = &ppp; 四級指針是 三級指針的位址。 【了解】
多級指針,不能 跳躍定義!
對應關系:
ppp == &pp; 三級指針
*ppp == pp == &p; 二級指針
**ppp == *pp == p == &a 一級指針
***ppp == **pp == *p == a 普通整型變量
*p : 将p變量的内容取出,當成位址看待,找到該位址對應的記憶體空間。
如果做左值: 存資料到空間中。
如果做右值: 取出空間中的内容。