C language - analysis of pointers and array exercises

Foreword:

After learning the basic and advanced pointers , you already have a certain understanding of pointers. Next, you need to do questions to consolidate the knowledge you have learned.
Understanding of the array name:
the array name is the address of the first element of the array, but there are two exceptions

  1. sizeof (array name), the array name here represents the entire array, and the calculation is the size of the entire array.
  2. &Array name, the array name here is the entire array, and the address of the entire array is taken out.

1. One-dimensional array

#include <stdio.h>
int main()
{
    
    
    int arr1[] = {
    
     1,2,3,4 };
    printf("%d\n", sizeof(arr1));
    //16(计算整个数组的大小)
    printf("%d\n", sizeof(arr1+0));
    //4/8(数组名arr1是首元素地址,a+0还是首元素的地址,地址的大小为4/8个字节)
    printf("%d\n", sizeof(*arr1));
    //4(*arr1是首元素,大小是4个字节)
    printf("%d\n", sizeof(arr1+1));
    //4/8(arr1是首元素的地址,arr1+1是第二个元素的地址,地址大小为4/8个字节)
    printf("%d\n", sizeof(arr1[1]));
    //4(arr1[1]是第2个元素,大小是4个字节)
    printf("%d\n", sizeof(&arr1));
    //4/8(&arr1是数组的地址,数组的地址也是地址,是地址那就是4/8个字节)
    printf("%d\n", sizeof(*&arr1));
    //16(&arr1是数组的地址,*&arr1是整个数组的元素,是16个字节)
    printf("%d\n", sizeof(&arr1+1));
    //4/8(&arr1是整个数组的地址,&arr1+1是跳过了整个数组的下一个地址,是地址那就是4/8个字节)
    printf("%d\n", sizeof(&arr1[0]));
    //4/8(arr1[0]是首元素,&arr1[0]是首元素的地址,是地址那就是4/8个字节)
    printf("%d\n", sizeof(&arr1[0]+1));
    //4/8(&arr1[0]是首元素的地址,&arr1[0]+1是第二个元素的地址,是地址那就是4/8个字节)
    return 0;
}

Second, the character array

#include <stdio.h>
#include <string.h>
int main()
{
    
    
    char arr2[] = {
    
     'a','b','c','d','e','f' };
    printf("%d\n", sizeof(arr2));
    //6(数组名单独放在sizeof内部,这里的arr2表示整个数组,计算的是整个数组的大小,单位是字节,大小为6个字节)
    printf("%d\n", sizeof(arr2+0));
    //4/8(arr2表示数组的首元素地址,arr2+0还是数组的首元素地址,是地址就是4/8个字节)
    printf("%d\n", sizeof(*arr2));
    //1(arr2表示数组的首元素地址,*arr2表示首元素,大小为1个字节)
    printf("%d\n", sizeof(arr2[1]));
    //1(arr2[1]表示第二个元素,大小为1个字节)
    printf("%d\n", sizeof(&arr2));
    //4/8(&arr2是整个数组的地址,是地址就是4/8个字节)
    printf("%d\n", sizeof(&arr2+1));
    //4/8(&arr2是整个数组的地址,&arr2+1是跳过整个数组后的地址,是地址就是4/8个字节)
    printf("%d\n", sizeof(&arr2[0]+1));
    //4/8(&arr2[0]是数组的首元素地址,&arr2[0]+1是第二个元素的地址,是地址那就是4/8个字节)

    printf("%d\n", strlen(arr2));
    //随机值(因为字符数组中没有\0,所以求字符长度的时候,会一直往后找,产生的结果是随机值)
    printf("%d\n", strlen(arr2+0));
    //随机值(arr2+0是数组的首元素地址,是随机值)
    printf("%d\n", strlen(*arr2));
    //非法访问(arr2是数组的首元素地址,*arr2是数组首元素,就是字符‘a’也是97,strlen就从97这个地址开始访问,统计字符串长度,非法访问)
    printf("%d\n", strlen(arr2[1]));
    //非法访问(arr2[1]是第二个元素‘b’,以第二个元素的值为地址开始访问,统计字符串长度,非法访问)
    printf("%d\n", strlen(&arr2));
    //随机值(&arr2是整个数组的地址,数组的地址和数组首元素的地址,值是一样的,传递给strlen函数,从数组第一个位置开始统计字符串长度,结果是随机值)
    printf("%d\n", strlen(&arr2+1));
    //随机值(&arr2是整个数组的地址,&arr2+1跳过整个数组后的地址,然后开始统计字符串长度,结果为随机值)
    printf("%d\n", strlen(&arr2[0]+1));
    //随机值(&arr2[0]是首元素的地址,&arr2[0]+1是第二个元素的地址,从第二个元素地址开始统计字符串长度,结果为随机值)

    char arr3[] = "abcdef";
    printf("%d\n", sizeof(arr3));
    //7(计算整个数组的大小,‘\0’也统计在内,为7个字节)
    printf("%d\n", sizeof(arr3 + 0));
    //4/8(arr3为数组首元素地址,arr3 + 0也是数组首元素地址,是地址就是4/8个字节)
    printf("%d\n", sizeof(*arr3));
    //1(arr3为数组首元素地址,*arr3为数组首元素,首元素为1个字节)
    printf("%d\n", sizeof(arr3[1]));
    //1(arr3[1]为第二个元素,占1个字节)
    printf("%d\n", sizeof(&arr3));
    //4/8(&arr3为整个数组的地址,是地址那就是4/8个字节)
    printf("%d\n", sizeof(&arr3 + 1));
    //4/8(&arr3为整个数组的地址,&arr3 + 1跳过整个数组后的地址,是地址那就是4/8个字节)
    printf("%d\n", sizeof(&arr3[0] + 1));
    //4/8(&arr3[0]是首元素的地址,&arr3[0] + 1是第二个元素的地址,是地址那就是4/8个字节)

    printf("%d\n", strlen(arr3));
    //6(计算字符串的长度,为6)
    printf("%d\n", strlen(arr3 + 0));
    //6(arr3为首元素地址,arr3 + 0还是首元素地址,从首元素地址开始访问,统计字符串长度,字符串长度为6)
    printf("%d\n", strlen(*arr3));
    //非法访问(*arr3为数组首元素的值,非法访问)
    printf("%d\n", strlen(arr3[1]));
    //非法访问(arr3[1]为第二个元素'b',ASCII码值就是98,地址为98,开始统计字符串长度,非法访问)
    printf("%d\n", strlen(&arr3));
    //6(&arr3整个数组的地址,也是首元素地址,字符串长度为6)
    printf("%d\n", strlen(&arr3 + 1));
    //随机值(&arr3 + 1是跳过整个数组后的地址,然后开始访问,统计字符串长度,为随机值)
    printf("%d\n", strlen(&arr3[0] + 1));
    //5(&arr3[0] + 1是第二个元素的地址,从第二个元素开始统计字符串长度,长度为5)

    char* p = "abcdef";
    printf("%d\n", sizeof(p));
    //4/8(p是一个指针变量)
    printf("%d\n", sizeof(p+1));
    //4/8(p+1指向第二个元素的地址)
    printf("%d\n", sizeof(*p));
    //1(第一个元素,大小为1个字节)
    printf("%d\n", sizeof(p[0]));
    //1(数组法,第一个元素,大小为1个字节)
    printf("%d\n", sizeof(&p));
    //4/8(&p指向的是p的地址,类型是char**,是地址那就是4/8个字节)
    printf("%d\n", sizeof(&p + 1));
    //4/8(&p + 1指向的是‘\0’后面的地址,是地址那就是4/8个字节)
    printf("%d\n", sizeof(&p[0] + 1));
    //4/8(&p[0] + 1指向第二个元素的地址,得到的是‘b’的地址,是地址那就是4/8个字节)


    printf("%d\n", strlen(p));
    //6(p指向字符串首地址)
    printf("%d\n", strlen(p+1));
    //5(p+1指向字符串第二个元素首地址)
    printf("%d\n", strlen(*p));
    //非法访问(*p是—>‘a’,以‘a’为地址访问,统计字符串长度,非法访问)
    printf("%d\n", strlen(p[1]));
    //非法访问(p[1]为第二个元素‘b’,以‘b’为地址访问,统计字符串长度,非法访问)
    printf("%d\n", strlen(&p));
    //随机值(&p指向的是p的地址,类型是char**)
    printf("%d\n", strlen(&p + 1));
    //随机值(&p+1,指向的是字符串‘\0’后面的地址,)
    printf("%d\n", strlen(&p[0] + 1));
    //5(&p[0] + 1第二个元素的地址,从第二个元素地址统计字符串长度,长度为5)
    return 0;
}

Three, two-dimensional array

#include <stdio.h>
int main()
{
    
    
    int a[3][4] = {
    
     0 };
    printf("%d\n", sizeof(a));
    //3*4*4=48(整个数组的字节)
    printf("%d\n", sizeof(a[0][0]));
    //4(二维数组第一个元素的字节)
    printf("%d\n", sizeof(a[0]));
    //16(a[0]是第一行这个一维数组的数组名,数组名算是单独放在sizeof内部,计算的是整个数组的大小)
    printf("%d\n", sizeof(a[0]+1));
    //4/8(a[0]作为第一行的数组名,没有单独放在sizeof内部,没有&,那么a[0]表示数组的首元素地址,也就是a[0][0]的地址,所以a[0]+1是第一行第二个元素的地址,是地址那就是4/8个字节)
    printf("%d\n", sizeof(*(a[0]+1)));
    //4(计算第一行第二个元素的大小)
    printf("%d\n", sizeof(a+1));
    //4/8(a是数组首元素地址,是第一行的地址;a+1就是第二行的地址,类型是int(*)[4])
    printf("%d\n", sizeof(*(a+1)));
    //16(*(a+1)->a[1]->sizeof(*(a+1))->sizeof(a[1]),计算的是第二行的大小;a+1是第二行的地址,类型int(*)[4],*(a+1)访问的是第二行的数组)
    printf("%d\n", sizeof(&a[0]+1));
    //4/8(&a[0]是第一行的地址,&a[0]+1是第二行的地址,是地址那就是4/8个字节)
    printf("%d\n", sizeof(*( &a[0] + 1)));
    //16(第二行的大小)
    printf("%d\n", sizeof(*a));
    //16(a是数组首元素的地址,就是第一行的地址,*a就是第一行,*a—>*(a+0)—>a[0])
    printf("%d\n", sizeof(a[3]));
    //16(不访问,只看类型)
    return 0;
}

Expressions have two properties:

  1. Value attribute: 9
  2. Type attribute: s=a+2——>short
#include <stdio.h>
int main()
{
    
    
    int a = 7;
    short s = 4;
    printf("%d\n", sizeof(s = a + 2));
    printf("%d\n", s);
    return 0;
}

print:
2
4

4. Pointer topic

Topic 1:

#include <stdio.h>
int main()
{
    
    
    int a[5] = {
    
     1,2,3,4,5 };
    int* ptr = (int*)(&a + 1);
    printf("%d,%d", *(a + 1), *(ptr - 1));//打印  2,5
    return 0;
}

Topic 2:

#include <stdio.h>
//结构体大小为20个字节
struct test
{
    
    
    int num;
    char* pc;
    short date;
    char cha[2];
    short ba[4];
}*p;
int main()
{
    
    
    printf("%d\n", sizeof(struct test));
    printf("%p\n", p);
    printf("%p\n", p + 0x1);//p是结构体类型的指针,占20个字节,加1就是跳过一个结构体
    printf("%p\n", (unsigned long)p + 0x1);//无符号长整型是数值
    printf("%p\n", (unsigned int*)p + 0x1);//整型指针占4个字节
    return 0;
}

insert image description here
Topic 3:

#include <stdio.h>
int main()
{
    
    
    int a[4] = {
    
     1,2,3,4 };
    int* ptr1 = (int*)(&a + 1);
    int* ptr2 = (int*)((int)a + 1);
    printf("%x %x %x\n", *ptr1, ptr1[-1], *ptr2);
    return 0;
}

insert image description here
Analysis:
insert image description here
Topic 4:

#include <stdio.h>
int main()
{
    
    
    int a[3][2] = {
    
     (0,1),(2,3),(4,5) };
    int* p;
    p = a[0];//没有&,也不在sizeof内部,表示第一行首地址表示&a[0][0]
    printf("%d\n", p[0]);//打印   1(p[0]->*p,*p的值是1)
    return 0;
}

Topic 5:

#include <stdio.h>
int main()
{
    
    
    int a[5][5];//定义一位二维数组(类型为int(*)[5])
    int(*p)[4];//定义一个数组指针(类型为int(*)[4])
    p = a;
    printf("%p,%b\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//打印 ff ff ff fc      -4
    //-4
    //10000000 00000000 00000000 00000100原码
    //11111111 11111111 11111111 11111011反码
    //11111111 11111111 11111111 11111100补码
    //打印0xff ff ff fc
    return 0;
}

insert image description here
Analysis:
insert image description here
Topic 6:

#include <stdio.h>
int main()
{
    
    
    int aa[2][5] = {
    
     1,2,3,4,5,6,7,8,9,10 };
    int* ptr1 = (int*)(&aa + 1);
    int* ptr2 = (int*)(*(aa + 1));
    printf("%d,%d\n", *(ptr1 - 1), *(ptr2 - 1));//打印  10,5
    return 0;
}

Topic 7:

#include <stdio.h>
int main()
{
    
    
    char* a[] = {
    
     "work","at","alibaba"};
    char** pa = a;//a的首地址
    pa++;
    printf("%s\n", *pa);//打印at
    return 0;
}

Topic 8:

#include <stdio.h>
int main()
{
    
    
    char* c[] = {
    
     "ENTER","NEW","POINT","FIRST" };
    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;
}

insert image description here
analyze:
insert image description here

Guess you like

Origin blog.csdn.net/plj521/article/details/131879472