int|char數組在sizeof和strlen函數中的應用以及指針的應用

第一:數組名

通常狀況下,數組名就是數組首元素的地址,可是有如下兩種狀況除外。
    1. 數組名單獨做爲sizeof函數的參數,如sizeof(數組名); 表示的是整個數組所佔字節大小。
    2. 對數組名作取地址操做,即:&數組名; 表明的是整個數組。即整個數組的地址,其+1操做是跨過整個數組長度大小。

第二:sizeof()庫函數在覺得整型數組中的應用

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|char數組在sizeof和strlen函數中的應用以及指針的應用

第三:一維字符數組在sizeof()函數中的應用

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;
}

int|char數組在sizeof和strlen函數中的應用以及指針的應用

第四:一維字符數組在strlen中的應用

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|char數組在sizeof和strlen函數中的應用以及指針的應用

第五:用常量字符串進行初始化的一維數組關於sizeof的應用

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|char數組在sizeof和strlen函數中的應用以及指針的應用

第六:用常量字符串進行初始化的一維數組關於strlen的應用

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|char數組在sizeof和strlen函數中的應用以及指針的應用

第七:用常量字符串進行初始化的字符指針關於sizeof的應用

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|char數組在sizeof和strlen函數中的應用以及指針的應用

第八:用常量字符串進行初始化的字符指針關於strlen的應用

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|char數組在sizeof和strlen函數中的應用以及指針的應用

第九:二維數組在sizeof中的應用

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|char數組在sizeof和strlen函數中的應用以及指針的應用

第十:公司面試題解析

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;
}

它們之間的分佈狀況以下:
int|char數組在sizeof和strlen函數中的應用以及指針的應用
結果以下:
int|char數組在sizeof和strlen函數中的應用以及指針的應用面試

相關文章
相關標籤/搜索