2024-08-17指针和数组试题解析

//

//    printf(“%d\n”, sizeof(a+0));// 输出为 4 / 8

//    // 因为 sizeof()的括号里放的不是数组名,而是 首元素地址 + 0,即sizeof(&a[0])

//

//    printf(“%d\n”, sizeof(*a));// 4  因为 a 没有 &(取地址),没有单独放在sizeof()里

//    // 这里求的是 首元素 的内存大小,*a 就是首元素

//

//    printf(“%d\n”, sizeof(a+1));// 4 / 8  与a + 0 的意思是一样的,只是现在这里跳过一个元素

//    // 这里是在求第二个元素的内存大小

//

//    printf(“%d\n”, sizeof(a[1]));// 4

//

//    printf(“%d\n”, sizeof(&a));// 4 / 8 &a 取出的是数组的地址

//    // 但 数组的地址也是地址 : 32位 / 64 位

//

//    printf(“%d\n”, sizeof(*&a));// 16 一个数组的地址,解引用 访问整个数组,可以说解引用和取地址相互抵消了

//

//    printf(“%d\n”, sizeof(&a+1));// 4 / 8  &a,拿出的是a的地址,+1跳过整个数组,但还是一个地址

//

//    printf(“%d\n”, sizeof(&a[0]));// 4 / 8 第一个元素的内存大小

//    printf(“%d\n”, sizeof(&a[0]+1));// 4 / 8 第二个元素的内存大小

//    return 0;

//}

// 字符数组

//#include<stdio.h>

//int main()

//{

//    char arr[] = { ‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’ };

//    printf(“%d\n”,sizeof(arr));// 6

//    printf(“%d\n”, sizeof(arr+0));//4 / 8  首元素地址+ 0,还是一个地址

//    printf(“%d\n”, sizeof(*arr));// 1   *arr(对首元素地址进行解引用) == 首元素

//    printf(“%d\n”, sizeof(arr[1]));// 1  第二个元素的大小

//    printf(“%d\n”, sizeof(&arr));// 4 / 6  这里是一个地址

//    printf(“%d\n”, sizeof(&arr+1));// 4 / 8  这里还是一个地址

//    printf(“%d\n”, sizeof(&arr[0]+1));// 4 / 8 一个地址

//    return 0;

//}

//#include<stdio.h>

//#include<string.h>

//int main()

//{

//    char arr[] = { ‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’ };

//    printf(“%d\n”, strlen(arr));//  随机值, 没有’\0’

//    printf(“%d\n”, strlen(arr + 0));// 随机值

//    //printf(“%d\n”, strlen(*arr));// *arr == ‘a’ == 97 strlen(把97当成一个地址),非法访问,程序崩溃

//    //printf(“%d\n”, strlen(arr[1]));// 与上表达式一样, 非法访问,程序崩溃

//    printf(“%d\n”, strlen(&arr));//  随机值

//    printf(“%d\n”, strlen(&arr + 1));//  随机值 - 6 ,与上表示式的随机值 ,相差 6

//    printf(“%d\n”, strlen(&arr[0] + 1));// 随机值 - 1,与 上上 表达式的随机值,相差 1

//    return 0;

//}

//#include<stdio.h>

//#include<string.h>

//int main()

//{

//    char arr[] = “abcdef”;

//    printf(“%d\n”, sizeof(arr));// 7  后面隐藏一个元素 ‘\0’

//    printf(“%d\n”, sizeof(arr + 0));// 4 / 8 是一个地址,

//    printf(“%d\n”, sizeof(*arr));//  1   *arr == 首元素,这里计算的是首元素的内存大小

//    printf(“%d\n”, sizeof(arr[1]));// 1  计算第二个元素的内存大小

//    printf(“%d\n”, sizeof(&arr));// 4 / 8  ,这是一个地址

//    printf(“%d\n”, sizeof(&arr + 1));// 4 / 8 ,这是一个地址

//    printf(“%d\n”, sizeof(&arr[0]) + 1);// 4 / 8, 这是一个地址

//

//

//

//    printf(“%d\n”, strlen(arr));//   6   遇到’\0’停止计数,'\0’不计入在内

//    printf(“%d\n”, strlen(arr + 0));//  6  从首元素开始计数,遇到’\0’停止计数,'\0’不计入在内

//    printf(“%d\n”, strlen(*arr));//   *arr  ==  a == 97,以97为地址( 从 97 开始计算直到遇到’\0’ ),属于非法访问,程序崩溃

//    printf(“%d\n”, strlen(arr[1]));//  arr[1]  ==  b == 98,以98为地址( 从 98 开始计算直到遇到’\0’ ),属于非法访问,程序崩溃

//    printf(“%d\n”, strlen(&arr));//  6 从首元素开始计数,遇到’\0’停止计数,'\0’不计入在内

//    printf(“%d\n”, strlen(&arr + 1));// 随机值,跳过了一个数组,从 ‘\0’ 后面 开始计数,直到遇到’\0’停止计数,'\0’不计入在内

//    printf(“%d\n”, strlen(&arr[0]) + 1);// 5 从第二个元素开始计数,遇到’\0’停止计数,'\0’不计入在内

//

//    return 0;

//}

//#include<stdio.h>

//#include<string.h>

//int main()

//{

//    char* p = “abcdef”;

//    printf(“%d\n”, sizeof§);// 4  / 8    a 的地址

//    printf(“%d\n”, sizeof(p + 0));// 4 / 8 b 的地址,

//    printf(“%d\n”, sizeof(*p));//  1   *arr == 首元素 a,这里计算的是首元素的内存大小

//    printf(“%d\n”, sizeof(p[0]));// 1  计算第一个元素的内存大小 p[0] == *(p+0) == a

//    printf(“%d\n”, sizeof(&p));//  4 / 8  把指针变量本身的地址取出来了,是一个地址

//    printf(“%d\n”, sizeof(&p + 1));// 4 / 8      地址

//    printf(“%d\n”, sizeof(&p[0]) + 1);// 4 / 8, b 的地址

//

//

//

//    printf(“%d\n”, strlen§);//  6  指针变量 p 存的是 a的地址,从p开始计算,直到遇到’\0’停止,'\0’不计入在内

//    printf(“%d\n”, strlen(p + 1));// 5  指针变量 p 存的是 b 的地址,从p开始计算,直到遇到’\0’停止,'\0’不计入在内

//    printf(“%d\n”, strlen(*p));//  *p == a == 97,以97为地址( 从 97 开始计算直到遇到’\0’ ),属于非法访问,程序崩溃

//    printf(“%d\n”, strlen(p[0]));//  p[0] == a == 97,以97为地址( 从 97 开始计算直到遇到’\0’ ),属于非法访问,程序崩溃

//    printf(“%d\n”, strlen(&p));// 随机值, 这里是指针变量 p 的地址,不是a的地址

//    printf(“%d\n”, strlen(&p + 1));// 随机值,

//    printf(“%d\n”, strlen(&p[0]) + 1);//  5  取出第一个元素的地址加一,到第 二 个元素,从第二个元素计算,直到遇到’\0’停止,'\0’不计入在内

//

//    return 0;

//}

// 二维数组

//#include<stdio.h>

//#include<string.h>

//int main()

//{

//    int a[3][4] = { 0 };

//    printf(“%d\n”, sizeof(a));//  48       3*4*4 = 12*4 = 48

//    printf(“%d\n”, sizeof(a[0][0]));// 4  第一行第一个元素

//    printf(“%d\n”, sizeof(a[0]));//  16 把第0行看成一个一维数组,a[0]就是一个一维数组的数组名,所以计算的整个第 0 行元素的内存大小 4 * 4 = 16

//    printf(“%d\n”, sizeof(a[0] + 1));//  4 / 8   第0行 第2个元素的地址

//    printf(“%d\n”, sizeof(*(a[0] + 1)));//  4    第0行 第2个元素

//

//    printf(“%d\n”, sizeof(a + 1));// 4  / 8     第1行 的 一维数组 的 地址

//    printf(“%d\n”, sizeof(*(a + 1)));// 16   解引用 第一行的一维数组的数组名(首元素)的地址,等于就是找到第一行的一维数组的数组名,

//                                     //sizeof(第一行 的 数组名 ),所以计算的是整个第一行元素的内存大小

//

//    printf(“%d\n”, sizeof(&a[0] + 1));//  4 / 8   第 1 行(第一行的一维数组名)的 地址,

//    printf(“%d\n”, sizeof(*(&a[0]) + 1));// 16 解引用 第 1 行(第一行的一维数组名)的 地址,等于找到了 第 1 行的一维数组的数组名

//                                         //sizeof(第一行 的 数组名 ),所以计算的是整个第一行元素的内存大小

//    printf(“%d\n”, sizeof(*a));// 16  a是首元素的地址(第 0 行的数组地址) ,*a(解引用 a )找到了第0行数组名,

//                               //计算的是整个第 0 行所有元素的内存大小

//    printf(“%d\n”, sizeof(a[3]));//16  ,另外  sizeof()括号里表达式不会计算,也就是说不会真的访问第四行数据,它只是把第四行的数组名放在这里()

//                                 //意思这里有第四行,就意味着 第四行 有 它自己 的 类型  ,其实这里  a[3] 跟 a[0] 一样的道理,

//                                 //a[3] 是第四行的数组名,那有 第四行吗?其实没有,但并不妨碍,因为我们不去访问

//                                 // 而且 sizeof() 括号里的 表达式 是不参与真是运算的 ,只是 根据 它的类型 计算 它的大小

//                                // 所以 a[3] 是一个一维数组,而且有 4 个整形的一维数组,sizeof(a[3]) == 4 * 4 == 16

//

//    return 0;

//}

//指针题

//#include<stdio.h>

//int main()

//{

//    int a[5] = { 1, 2, 3, 4, 5 };

//    int* ptr = (int*)(&a + 1);// 数组的指针类型,不能放进一个整形指针里,所以这里强制类型转换,但值没有发生变换,

//                             // 存的值,还是跳过一个数组的指向的那个值(未知量)

//    printf(“%d,%d\n”, *(a + 1), *(ptr - 1));// 整形指针 ptr 减一,指向 5 的 那个位置,再解引用就是5

//    return 0;         //  2         5

//}

//struct test

//{

//    int num;

//    char* pcname;

//    short s_date;

//    char cha[2];

//    short s_ba[4];

//}* p;

// 假设 p 的 值为  0x10 00 00 00,如下表达式分别为多少

// 已知结构体 test 类型 的 变量 大小为 20个字节

//#include<stdio.h>

//int main()

//{

//    p = (struct test*)0x100000;

//    printf(“%p\n”, p + 0x1);// 0x1 == 1 这里加1 等于跳过了一个结构体(20字节)

//    //0x10 00 00 + 20 ==0x10 00 14  因为 %p(32位)

//    //打印  0x 00 10 00 14

//

//    printf(“%p\n”, (unsigned long)p + 0x1); // 强制类型转换 无符号长整形类型,0x100000 转换为 10 进制 -> 1048576 + 1 = 1048577 -> 0x10 00 01

//         // %p, 即0x 00 10 00 01

//

//    printf(“%p\n”, (unsigned int*)p + 0x1);//强制类型转换 无符号整形指针类型 加1 == 就是跳过一个无符号整形指针(4 byte)

//    // 即 0x 00 10 00 04

//    return 0;

//}

//#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”, ptr1[-1], *ptr2);// %x 十六进制数

//    return 0;     //   4      2 000 000

//}

1                 2                    3                   4

01 00 00 00        02 00 00 00         03 00 00 00         04 00 00 00

低地址                                                         高地址(小端 存储:低字节存低地址,高字节存高地址)

a 是数组名(首元素地址),指向 1 所在的地址(01前面)。这时类型强制转换 整形,加1(1字节),

再将他转换为一个地址,在对其解引用 ,此时它(ptr2)指向 01 的后面,又因为ptr2是int 类型

也就是说它一次访问 4 个字节的内容( 00 00 00 02 ) 取出来使反着读取(从高位开始读取),02 00 00 00

按十六进制 输出 (0x 02 00 00 00) 即,2 000 000

//#include<stdio.h>

//int main()

//{                  //    1       3         5

//    int a[3][2] = { ( 0, 1 ), ( 2, 3 ), ( 4, 5) };

//    int* p;         //逗号表达式,以最后一个表达式结果为准

//                   //  数组存储情况     1 3

//                   //                   5 0

//                   //                   0 0

//    p = a[0];

//    printf(“%d\n”,p[0]); //  1

//    return 0;

//}

//#include<stdio.h>

//int main()

//{

//    int a[5][5];

//    //    a[0]        a[1]         a[2]         a[3]           a[4]

//    // 口口口口口  口口口口口   口口口口口   口口口口口     口口口口口

//    // |       |         |          |          |   |            |

//    //p[0]   p[1]      p[2]       p[3]       p[4]  |        a[4][2]

//    //                                           p[4][2]

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值