Zlib是一個開源的數據壓縮庫,提供了一種通用的數據壓縮和解壓縮演算法。它最初由`Jean-Loup Gailly`和`Mark Adler`開發,旨在成為一個高效、輕量級的壓縮庫,其被廣泛應用於許多領域,包括網路通信、文件壓縮、資料庫系統等。其壓縮演算法是基於`DEFLATE`演算法,這是一種無損數據壓... ...
C語言【指針1】
1、指針類型長度隨操作系統,64位操作系統為8Byte。
具體說一下:地址相當於門牌號,一般一個地址指向的空間是一個位元組(下麵按一個位元組敘述,電腦底層也許也有按雙位元組編碼的)。對於64位機器,某一個地址有64位,所以在空間里存那某一個地址時,這64位即8Byte。這64位總共能表示的數量(即定址數量)為2^64,十六進位0x0000000000000000到0xffffffffffffffff,這個數很大很大,以現在的記憶體空間來看,如果一個地址指向的空間是1Byte,根本用不完。
2、 %p為輸出指針的占位符;&為取址運算符;*為取值運算符(即取地址對應的數據)。
3、指針一些基礎知識,以代碼為例。
int a = 100;
/**
* 下麵的代碼是聲明並初始化。
* 之後想要改變指針指向,要修改p而不是*p(這裡聲明並初始化時用*p是指明定義的是一個指針)。
* 之後想要改變變數a的值,修改*p即可。
*/
int* p = &a;
*p = 200; // 修改*p時,a也會跟著改變
printf("%p\n", &a); // 輸出a的地址
printf("%p\n", p); // 輸出a的地址
printf("%d\n", a); // 輸出a的值
printf("%d\n", *p); // 輸出a的值
printf("%p\n", &p); // 輸出p的地址。p本身也有地址指向它,它也是個空間,空間里存的地址。
指針就是個變數,存的別的數據地址,如果存自己的地址,那沒啥意義。
指針就是個變數,它是p而不是* p。* p是那個數據,參考上面代碼。
數組名、函數名等就是地址本身(或者說是表示數組或函數首地址的常量),所以,可以通過數組名給指針的方式使指針指向數組,反之不行,數組名和函數名不可更改。
/**
* 如果把指針賦給普通整型變數,可以。但如果想像*指針一樣給這個變數加 * ,就不行了。
*/
int a = 100;
int * p = &a;
long long la = p;
*la; // 會報錯。
/**
* 不同指針類型
*/
int a = 100;
int* p = &a;
double * p1 = p; // p1和p空間里的位元組數一樣,但去a那找的寬度不一樣。* p1 去a那要找8Byte.
/**
* 野指針問題
*/
int * p; // 一個野指針
*p = 100; // 如果p是在函數里定義的,直接修改隨機指向里的值,不會報錯,但可能使程式崩掉。
指針的運算,即地址的運算,只不過指針可以接收運算的結果,而地址不行。
1.指針(地址)只能和整數作加減運算(包括兩地址相加減)。本質就是地址的運算,指針可以接收結果。
對於int類型的指針來說,p+=1即p往後(高位)移動了4個位元組。其他類型同理。
2.同類型指針相減,得到一個ptrdiff_t類型的數據。其占位符為 %td 。
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int *p1 = &arr[0]; // int * p1 = arr;
int *p2 = &arr[3]; // int * p2 = arr+3;
p1[2]; // 等同arr[2] 指定數組後,指針可以這樣使用
p2[2]; // arr[5], 看第三行代碼
printf("%td\n", p1 - p2); // -3 兩地址相差3,(自動除過int的位元組數)
3.指針(地址)也可以作比較運算。棧先進後出,所以在函數中,一般先初始化的放在高地址,指針指向的時候可比較指向變數的地址大小。
4、指針和數組名的區別與共用。
-
區別
指針是變數,數組名是常量。
sizeof(數組名) 返回為整個數組的位元組數;當指針指向數組後,sizeof(指針) 返回仍然是跟隨系統的位元組數。
-
相同。數組除了不能隨意修改或指向外,基本可以當指針使用;當指針指向數組後,指針可以使用數組的所有方式操作數組。舉個例子:
int arr[20] = {10, 20, 30, ...}; printf("%d\n", (arr+1)[0]); // 20。 這裡arr+1並沒有修改arr的值。這個(arr+1)[0]可替換為*(arr+1).
5、指針數組。int *p[10]; 指針數組是一個大數組,裡面存放的是一個個的指針。
* p[1] 和*(p[1])是一樣的。表示第二個數組元素中指針指向的數值。
int a = 10, b = 20;
int *p[2] = {&a, &b};
printf("%d %d\n", *p[0], *p[1]); // 10 20
6、數組指針。int (*p)[10]; 數組指針是一個指針,裡面存放了一個數組。[10]表示這個二維的p加一就跳10個長度。這裡這個p是一個二維的指針。
int (*p)[3]; // p+1即跳3個元素
int arr[2][3] = {1, 2, 3, 4, 5, 6};
p = arr; // 這裡是二維的,就不加&了
printf("%d\n", (*(p+1))[0]); // 跳三個加個*再取數組第一個元素
補一個案例
int a = 256;
int* p = &a;
// int* p = &a + 1; // 這裡+1的話也是加了4返回給p
long long p1 = p; // 這裡就是為了下麵可以加真實的數,而不是加定義類型的倍數
p = p1+1; // 真正的+1 而不是+4
*p = 10;
printf("%d\n", a); // 2560 湊巧10倍了
printf("%d\n", *p); // 10
// 這個程式就是往左移了一個位元組再改數,回到之前的變數輸出混亂的值。
再補一個
int arr[5] = {10, 20, 30, 40, 50};
int (*ptr1)[5] = &arr;
printf("%d\n", ptr1 == arr); // 1 但警報,不報錯
printf("%d\n", *ptr1 == arr); // 1
printf("%d\n", ptr1+1 == arr+1); //0 arr+1是第二個元素的地址, ptr1+1 越界了,就不可能等了