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的参数为一个地址。

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函数中的应用以及指针的应用

猜你喜欢

转载自blog.51cto.com/15132389/2683455