通常狀況下,數組名就是數組首元素的地址,可是有如下兩種狀況除外。 1. 數組名單獨做爲sizeof函數的參數,如sizeof(數組名); 表示的是整個數組所佔字節大小。 2. 對數組名作取地址操做,即:&數組名; 表明的是整個數組。即整個數組的地址,其+1操做是跨過整個數組長度大小。
int main() { // 一維整型數組的用sizeof函數計算所佔字節大小 int arr[] = { 1,2,4,8,16 }; printf("%d ", sizeof(arr)); // 20 整個數組所佔字節大小:4 * 5 = 20 printf("%d ", sizeof(arr + 0)); // 4 | 8 首元素的地址,即地址所佔字節:固定 printf("%d ", sizeof(*arr)); // 4 首元素所佔字節大小,即int | 1所佔字節大小:4 printf("%d ", sizeof(arr + 1)); // 4 | 8 第二個元素的地址所佔字節大小:是固定的 printf("%d ", sizeof(arr[1])); // 4 第二個元素所佔字節大小,即int | 2所佔字節大小:4 printf("%d ", sizeof(&arr)); // 4 | 8 數組的地址所佔字節大小:固定大小,該地址+1是跳過整個數組 printf("%d ", sizeof(*&arr)); // 20 整個數組所佔字節大小(*&arr等同於a),即&arr是獲得整個數組的地址,對其解引用獲得的是整個數組,故爲4 * 5 = 20; printf("%d ", sizeof(&arr + 1));// 4 | 8 指向數組最後一個元素後面所在內存地址的大小:固定大小 printf("%d ", sizeof(&arr[0])); // 4 | 8 首元素地址所佔字節大小:固定 printf("%d ", sizeof(&arr[0] + 1)); //4|8第二個元素地址所佔字節大小:固定 return 0; }
int main() { // 一維字符數組的用sizeof函數計算所佔字節大小 char str[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g'}; printf("%d ", sizeof(str)); // 7 整個數組所佔字節大小:1 * 7 = 7 printf("%d ", sizeof(str + 0)); // 4 | 8 首元素的地址,即地址所佔字節:固定 printf("%d ", sizeof(*str)); // 1 首元素所佔字節大小,即char | 'a'所佔字節大小:1 printf("%d ", sizeof(str + 1)); // 4 | 8 第二個元素的地址所佔字節大小:是固定的 printf("%d ", sizeof(str[1])); // 1 第二個元素所佔字節大小,即char | 'b'所佔字節大小:1 printf("%d ", sizeof(&str)); // 4 | 8 數組的地址所佔字節大小:固定大小,該地址+1是跳過整個數組 printf("%d ", sizeof(*&str)); // 7 整個數組所佔字節大小(*&str等同於str),即&str是獲得整個數組的地址,對其解引用獲得的是整個數組,故爲1 * 7 = 7; printf("%d ", sizeof(&str + 1));// 4 | 8 指向數組最後一個元素後面所在內存地址的大小:固定大小 printf("%d ", sizeof(&str[0])); // 4 | 8 首元素地址所佔字節大小:固定 printf("%d ", sizeof(&str[0] + 1)); //4|8第二個元素地址所佔字節大小:固定 return 0; }
strlen函數計算字符串長度,其在內存中遇到'\0',則結束計算
strlen的參數爲一個地址。python
int main() { char str[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' }; printf("%d ", strlen(str)); // 隨機值 str爲首元素的地址,從該位置向後訪問,直到遇到'\0'時,結束 printf("%d ", strlen(str + 0)); // 隨機值 str+0也爲首元素的地址,從該位置向後訪問,直到遇到'\0'時,結束 // printf("%d ", strlen(*str)); // ERROR 傳的是‘a’,其ascll爲97,即從內存爲97的位置開始訪問,屬於非法訪問內存 // 0x538AFF5C (ucrtbased.dll)處(位於 指針進階.exe 中)引起的異常: 0xC0000005: 讀取位置 0x00000061 時發生訪問衝突 // printf("%d ", strlen(str[1])); // ERROR 同上 讀取0x00000062時(十進制:98)發生訪問衝突 // 0x52BDFF5C (ucrtbased.dll)處(位於 指針進階.exe 中)引起的異常: 0xC0000005: 讀取位置 0x00000062 時發生訪問衝突。 printf("%d ", strlen(str + 1)); // 隨機值 - 1 從數組的第二個元素所在地址開始向後訪問 printf("%d ", strlen(&str)); // 隨機值 從數組的地址(和數組首元素地址相同)的位置開始向後訪問 printf("%d ", strlen(*&str)); // 隨機值 整個數組所佔字節大小(*&str等同於str),即&str是獲得整個數組的地址,對其解引用獲得的是整個數組,從首元素處開始向後訪問; printf("%d ", strlen(&str + 1));// 隨機值 - 7 從數組最後一個元素後面所在內存地址開始訪問 printf("%d ", strlen(&str[0])); // 隨機值 從數組首元素地址處開始向後訪問 printf("%d ", strlen(&str[0] + 1)); //隨機值 - 1 從數組第二個元素地址處開始向後訪問 return 0; }
int main() { // 一維字符數組(用常量字符串進行初始化, 數組中還存放了'\0'),用sizeof來計算所佔字節大小 char str[] = "abcdefg"; printf("%d ", sizeof(str)); // 8 整個數組所佔字節大小:1 * 8 = 8 printf("%d ", sizeof(str + 0)); // 4 | 8 首元素的地址,即地址所佔字節:固定 printf("%d ", sizeof(*str)); // 1 首元素所佔字節大小,即char | 'a'所佔字節大小:1 printf("%d ", sizeof(str + 1)); // 4 | 8 第二個元素的地址所佔字節大小:是固定的 printf("%d ", sizeof(str[1])); // 1 第二個元素所佔字節大小,即char | 'b'所佔字節大小:1 printf("%d ", sizeof(&str)); // 4 | 8 數組的地址所佔字節大小:固定大小,該地址+1是跳過整個數組 printf("%d ", sizeof(*&str)); // 8 整個數組所佔字節大小(*&str等同於str),即&str是獲得整個數組的地址,對其解引用獲得的是整個數組,故爲1 * 8 = 8; printf("%d ", sizeof(&str + 1));// 4 | 8 指向數組最後一個元素後面所在內存地址的大小:固定大小 printf("%d ", sizeof(&str[0])); // 4 | 8 首元素地址所佔字節大小:固定 printf("%d ", sizeof(&str[0] + 1)); //4|8第二個元素地址所佔字節大小:固定 return 0; }
int main() { // 一維字符數組(用常量字符串進行初始化, 數組中還存放了'\0'),用strlen來計算字符串的大小 char str[] = "abcdefg"; printf("%d ", strlen(str)); // 7 str爲首元素的地址,從該位置向後訪問,直到遇到'\0'時,結束:7 printf("%d ", strlen(str + 0)); // 7 tr+0也爲首元素的地址,從該位置向後訪問,直到遇到'\0'時,結束 //printf("%d ", strlen(*str)); // ERROR 傳的是‘a’,其ascll爲97,即從內存爲97的位置開始訪問,屬於非法訪問內存 printf("%d ", strlen(str + 1)); // 6 從數組的第二個元素所在地址開始向後訪問 //printf("%d ", strlen(str[1])); // ERROR 同上 讀取0x00000062時(十進制:98)發生訪問衝突 printf("%d ", strlen(&str)); // 7 從數組的地址(和數組首元素地址相同)的位置開始向後訪問 printf("%d ", strlen(*&str)); // 7 同strlen(str),即&str是獲得整個數組的地址,對其解引用獲得的是整個數組,故爲7 printf("%d ", strlen(&str + 1)); // 隨機值 從數組最後一個元素後面所在內存地址開始訪問 printf("%d ", strlen(&str[0])); // 7 從數組首元素地址處開始向後訪問 printf("%d ", strlen(&str[0] + 1)); // 6 從數組第二個元素地址處開始向後訪問 return 0; }
int main() { // 用字符指針變量接收一個常量字符串(是將該字符串的首字符的地址賦值給字符指針),用sizeof來計算所佔字節大小 char *pstr = "abcdefg"; printf("%d ", sizeof(pstr)); // 4 | 8 p是一個指針變量,其存的是地址,故其大小是固定的 printf("%d ", sizeof(pstr + 0)); // 4 | 8 字符串中首元素a的地址,即地址所佔字節:固定 printf("%d ", sizeof(*pstr)); // 1 字符串首元素a所佔字節大小,即char | 'a'所佔字節大小:1 printf("%d ", sizeof(pstr + 1)); // 4 | 8 字符串中第二個元素b的地址所佔字節大小:是固定的 printf("%d ", sizeof(pstr[1])); // 1 字符串第二個元素b所佔字節大小,即char | 'b'所佔字節大小:1 printf("%d ", sizeof(&pstr)); // 4 | 8 指針變量pstr的地址,是固定大小的。 printf("%d ", sizeof(*&pstr)); // 4 | 8 等同於sizeof(pstr) printf("%d ", sizeof(&pstr + 1));// 4 | 8 pstr的地址的下一個地址,是固定的 printf("%d ", sizeof(&pstr[0])); // 4 | 8 首元素地址所佔字節大小:固定 printf("%d ", sizeof(&pstr[0] + 1)); //4|8字符串中第二個元素b地址所佔字節大小:固定 return 0; }
int main() { // 用字符指針變量接收一個常量字符串(是將該字符串的首字符的地址賦值給字符指針),用strlen來計算所佔字節大小 char* pstr = "abcdefg"; printf("%d ", strlen(pstr)); // 7 pstr爲首元素的地址,從該位置向後訪問,直到遇到'\0'時,結束:7 printf("%d ", strlen(pstr + 0)); // 7 pstr+0也爲首元素的地址,從該位置向後訪問,直到遇到'\0'時,結束 //printf("%d ", strlen(*pstr)); // ERROR 傳的是‘a’,其ascll爲97,即從內存爲97的位置開始訪問,屬於非法訪問內存 printf("%d ", strlen(pstr + 1)); // 6 從字符串中的第二個元素b所在地址開始向後訪問 //printf("%d ", strlen(pstr[1])); // ERROR 同上 讀取0x00000062時(十進制:98)發生訪問衝突 printf("%d ", strlen(&pstr)); // 隨機值 從數組的地址(和數組首元素地址相同)的位置開始向後訪問 printf("%d ", strlen(*&pstr)); // 7 同strlen(str),即&str是獲得整個數組的地址,對其解引用獲得的是整個數組,故爲7 printf("%d ", strlen(&pstr + 1)); // 隨機值 從數組最後一個元素後面所在內存地址開始訪問 printf("%d ", strlen(&pstr[0])); // 7 從字符串中首元素a地址處開始向後訪問 printf("%d ", strlen(&pstr[0] + 1)); // 6 從字符串中第二個元素b地址處開始向後訪問 return 0; }
int main() { // 二維數組 用sizeof計算所佔字節大小 // 把一個二維數組當作一個一維數組時,則把其每一行當作一個元素, // 即每一個元素又是一個一維數組,其對應的數組名爲arr[i], i = 0 1 ... nrow - 1 // i行j列的值:arr[i][j] = *(arr[i] + j) = *(*(arr + i) + j) = *(arr + i)[j] int arr[2][3] = { 1,2,3,4,5,6 }; int i, j; for (i = 0; i < 2; i++) { for (j = 0; j < 3; j++) { printf("%p\t", &arr[i][j]); } printf("\n"); } printf("%d ", sizeof(arr)); // 24 整個數組所佔字節大小:2 * 3 * 4 = 24 printf("%d ", sizeof(arr[0][0])); // 4 數組中第一行第一列值所佔字節大小:int|1,爲4 printf("%d ", sizeof(arr[0])); // 12 arr[0]是二維數組中第一個元素|首元素|一維數組的數組名,計算的該數組的整個大小 printf("%d_%d ", sizeof(arr[0] + 1), *(arr[0] +1)); // 4_2, 此時arr[0]是一個一維數組中首元素的地址,+1則表明該一維數組中第二個元素的地址和值 printf("%d ", sizeof(*(arr[0] + 1))); // 4 | 8 第一行第二列元素所佔字節 printf("%d_%p ", sizeof(arr + 1), *(arr + 1)); // 4 | 8 第二行的地址,不是二維數組中第二個元素的地址(arr[1]) printf("%d ", sizeof(*(arr + 1))); // 12 等價於arr[1] 第二行(一維數組)的地址解引用獲得第二行(一維數組),二維數組中第二個元素|一維數組的數組名 printf("%d_%p ", sizeof(&arr[0] + 1), &arr[0] + 1); // 4 | 8 第二行的地址,一個一維數組的地址 printf("%d ", sizeof(*(&arr[0] + 1))); // 12 第二行的大小 printf("%d ", sizeof(*arr)); // 12 第一行的大小 printf("%d ", sizeof(arr[3])); // 12 第四行所對應的一維數組的數組名,表明整個一維數組的大小 return 0; }
int main() { // 解析: // 1. **++cpp // cpp指向的是數組cp中首元素的地址,++cpp則cpp指向數組cp中第二個元素的地址 // *++cpp: 對其進行解引用,獲得cp中第二個元素的內容:c+2 // **++cpp: 對其進行解引用,獲得c+2所指向的內容,而c+2是數組c中第三個元素的地址,即獲得數組c中第三個元素 // 數組c中第三個元素爲字符串"python"首字母的地址,對其進行打印,則獲得python // 2. *--*++cpp + 3 // ++cpp,則是cpp指向數組cp中下一個元素的地址,即c+1的地址 // *++cpp:對其進行解引用,獲得其指向的內容:c+1,對其進行--操做,即內容-1,即c+1-1 = c // *--*++cpp:對c進行解引用,獲得c指向的內容,c爲數組c首元素的地址,即獲得數組c的首元素,即字符串"hello"首字符的地址 // 對其進行+3操做,即獲得字符串"hello"中第二個l字符的地址,對其進行打印,獲得lo //3. *cpp[-2]+3 = *(*(cpp-2)) + 3 // 獲得cpp所指向內容的前面第二個內容(c+3)的地址,對其進行解引用獲得內容;c+3 // 對其進行及引用,獲得c+3所指向的內容,即數組c中第四個元素,即字符串"coming"首字符的地址,對其+3操做,獲得字符i的地址,對其打印,獲得ing //4. cpp[-1][-1] + 3 = *(*(cpp-1) - 1) + 3 // cpp - 1:指向cpp所指向的前面的地址:c+2的地址,解引用獲得c+2,即*(c+2 - 1) + 3 = *(c+1) + 3 // c+1: 是數組c中第二個元素的地址,對其解引用獲得數組c中第二個元素,即字符串"world"的首字符的地址, + 1 獲得字符o的地址,打印時,獲得orld char* c[] = { "hello", "world", "python", "coming" }; char** cp[] = { c + 3, c + 2, c + 1, c }; char*** cpp = cp; printf("%s\n", **++cpp); printf("%s\n", *--*++cpp + 3); printf("%s\n", *cpp[-2] + 3); printf("%s\n", cpp[-1][-1] + 1); // return 0; }
它們之間的分佈狀況以下:
結果以下:
面試