C语言数组与指针练习题


前言

在理解 C语言指针 的这篇文章的基础上,做下面的练习题可以更好地掌握数组与指针的知识。


七、练习

数组名表示数组首元素的地址

但是有2个例外:

  1. sizeof(数组名),数组名表示整个数组,计算的是数组的总大小,单位是字节。
  2. &数组名,数组名表示整个数组,&数组名 取出的是整个数组的地址

除此之外,所有遇到的数组名都表示数组首元素的地址。

*(arr + n) = arr[n]

7.1 一维数组

void test1()
{
    int a[] = { 1,2,3,4 };
    printf("%d\r\n", sizeof(a)); 
    printf("%d\r\n", sizeof(a + 0));
    printf("%d\r\n", sizeof(*a));
    printf("%d\r\n", sizeof(a + 1));
    printf("%d\r\n", sizeof(a[1]));
    printf("%d\r\n", sizeof(&a));
    printf("%d\r\n", sizeof(*&a));
    printf("%d\r\n", sizeof(&a + 1));
    printf("%d\r\n", sizeof(&a[0]));
    printf("%d\r\n", sizeof(&a[0] + 1));
}

void test1()
{
    int a[] = { 1,2,3,4 };

	// sizeof(数组名)计算的是数组的总大小
    printf("%d\r\n", sizeof(a)); // 16
    
    // 数组名a是数组首元素的地址,32位程序的地址是4字节
    printf("%d\r\n", sizeof(a + 0)); // 4
    
    // 数组名a是数组首元素的地址,*a得到数组的首元素1,类型为int大小4字节
    // *(arr + n) = arr[n] 因此 *a=*(a+0)=a[0]
    printf("%d\r\n", sizeof(*a)); // 4
    
    // 数组名a是数组首元素的地址,a+1得到下一个元素的地址,地址为4字节大小
    printf("%d\r\n", sizeof(a + 1)); // 4
    
    // 数组元素类型为int大小4字节
    printf("%d\r\n", sizeof(a[1])); // 4
    
    // &数组名表示整个数组的地址,地址为4字节大小
    printf("%d\r\n", sizeof(&a)); // 4
    
    // &a为整个数组的地址,再解星号得到整个数组,相当于*与&抵消了,数组大小为16字节
    printf("%d\r\n", sizeof(*&a)); // 16
    
    // &a为整个数组的地址,加1得到越过数组a之后的地址,地址大小4字节
    printf("%d\r\n", sizeof(&a + 1)); // 4
    
    // 数组首元素的地址,地址大小4字节
    printf("%d\r\n", sizeof(&a[0])); // 4
 
    // 数组首元素的地址,类型为int*,加1表示下一个元素的地址,地址大小4字节
    printf("%d\r\n", sizeof(&a[0] + 1)); // 4
}

7.2 字符数组1

void test2()
{
    char arr[] = { 'a','b','c','d','e','f' };
    printf("%d\n", sizeof(arr));
    printf("%d\n", sizeof(arr + 0));
    printf("%d\n", sizeof(*arr));
    printf("%d\n", sizeof(arr[1]));
    printf("%d\n", sizeof(&arr));
    printf("%d\n", sizeof(&arr + 1));
    printf("%d\n", sizeof(&arr[0] + 1));

    printf("%d\n", strlen(arr));
    printf("%d\n", strlen(arr + 0));
    printf("%d\n", strlen(*arr));
    printf("%d\n", strlen(arr[1]));
    printf("%d\n", strlen(&arr));
    printf("%d\n", strlen(&arr + 1));
    printf("%d\n", strlen(&arr[0] + 1));
}

参考:

void test2()
{
    char arr[] = { 'a','b','c','d','e','f' };
    
    // sizeof(数组名)计算整个数组的大小
    printf("%d\n", sizeof(arr)); // 6
    
    // 数组名arr表示数组首元素的地址,加0还是数组首元素的地址,地址4字节大小
    printf("%d\n", sizeof(arr + 0)); // 4
    
    // arr表示数组首元素的地址,*arr得到数组首元素a,类型为char大小1字节
    printf("%d\n", sizeof(*arr)); // 1
    
    // 数组下标为1的元素为b,类型为char大小1字节
    printf("%d\n", sizeof(arr[1])); // 1
    
    // &arr为整个数组的地址,地址4字节大小
    printf("%d\n", sizeof(&arr)); // 4
    
    // &arr为整个数组的地址,加1得到越过整个数组的地址,地址大小4字节
    printf("%d\n", sizeof(&arr + 1)); // 4
    
    // 数组首元素的地址,加1得到下一个元素的地址,地址大小4字节
    printf("%d\n", sizeof(&arr[0] + 1)); // 4

    
    // arr数组首元素的地址,因'\0'位置不知,下面是一个随机数
    printf("%d\n", strlen(arr)); // 随机数,测试为19
    
    // 数组名arr表示数组首元素的地址,加0还是数组首元素的地址,因'\0'位置不知,下面是一个随机数
    printf("%d\n", strlen(arr + 0)); // 随机数,测试为19
    
    // 数组名arr表示数组首元素的地址,*arr得到首元素a,a作为strlen的参数,将计算地址为a的ascii码值97=0x61处字符串长度,将会出现内存访问异常的错误,error
    printf("%d\n", strlen(*arr));

    // 同上,将计算地址为b的ascii码值98=0x62处字符串长度,出现内存访问异常,error
    printf("%d\n", strlen(arr[1]));
    
    // &arr取得整个数组的地址,因'\0'位置不知,下面是一个随机数
    printf("%d\n", strlen(&arr)); // 随机数,测试为19
    
    // &arr取得整个数组的地址,加1得到越过整个数组的地址,因'\0'位置不知,下面是一个随机数
    printf("%d\n", strlen(&arr + 1)); // 随机数,测试为13
    
    // 数组首元素的地址,加1得到下一个元素的地址,因'\0'位置不知,下面是一个随机数
    printf("%d\n", strlen(&arr[0] + 1)); // 随机数,测试为18
}

7.3 字符数组2

void test3()
{
    char arr[] = "abcdef";
    printf("%d\n", sizeof(arr));
    printf("%d\n", sizeof(arr + 0));
    printf("%d\n", sizeof(*arr));
    printf("%d\n", sizeof(arr[1]));
    printf("%d\n", sizeof(&arr));
    printf("%d\n", sizeof(&arr + 1));
    printf("%d\n", sizeof(&arr[0] + 1));

    printf("%d\n", strlen(arr));
    printf("%d\n", strlen(arr + 0));
    printf("%d\n", strlen(*arr));
    printf("%d\n", strlen(arr[1]));
    printf("%d\n", strlen(&arr));
    printf("%d\n", strlen(&arr + 1));
    printf("%d\n", strlen(&arr[0] + 1));
}

参考:

void test3()
{
    char arr[] = "abcdef"; // 字符串在栈区,其自动包括'\0'
    
    // sizeof(数组名)计算整个数组的大小 
    printf("%d\n", sizeof(arr)); // 7
    
    // 数组名是数组首元素的地址,加0还是首元素的地址,地址大小4字节
    printf("%d\n", sizeof(arr + 0)); // 4
    
    // arr表示数组首元素的地址,*arr得到数组首元素a,类型为char大小1字节
    printf("%d\n", sizeof(*arr)); // 1
    
    // 数组下标为1的元素为b,类型为char大小1字节
    printf("%d\n", sizeof(arr[1])); // 1
    
    // &arr为整个数组的地址,地址4字节大小
    printf("%d\n", sizeof(&arr)); // 4
    
    // &arr为整个数组的地址,加1得到越过整个数组的地址,地址大小4字节
    printf("%d\n", sizeof(&arr + 1)); // 4
    
    // 数组首元素的地址,加1得到下一个元素的地址,地址大小4字节
    printf("%d\n", sizeof(&arr[0] + 1)); // 4

    
    // arr数组首元素的地址,strlen遇到'\0'结束,得到的长度不包括'\0'
    printf("%d\n", strlen(arr)); // 6
    
    // 数组名arr表示数组首元素的地址,加0还是数组首元素的地址,strlen遇到'\0'结束,得到的长度不包括'\0'
    printf("%d\n", strlen(arr + 0)); // 6
    
    // 数组名arr表示数组首元素的地址,*arr得到首元素a,a作为strlen的参数,将计算地址为a的ascii码值97=0x61处字符串长度,将会出现内存访问异常的错误,error
    printf("%d\n", strlen(*arr)); // error
    
    // 同上,将计算地址为b的ascii码值98=0x62处字符串长度,出现内存访问异常,error
    printf("%d\n", strlen(arr[1])); // error
    
    // &arr取得整个数组的地址,strlen遇到'\0'结束,得到的长度不包括'\0'
    printf("%d\n", strlen(&arr)); // 6
    
    // &arr取得整个数组的地址,加1得到越过整个数组的地址,因'\0'位置不知,下面是一个随机数
    printf("%d\n", strlen(&arr + 1)); // 随机数,测试为12
    
    // 数组首元素的地址,加1得到下一个元素的地址,strlen遇到'\0'结束,得到的长度不包括'\0'
    printf("%d\n", strlen(&arr[0] + 1)); // 5
}

7.4 字符串指针

void test4()
{
    char* p = "abcdef";
    printf("%d\n", sizeof(p));
    printf("%d\n", sizeof(p + 1));
    printf("%d\n", sizeof(*p));
    printf("%d\n", sizeof(p[0]));
    printf("%d\n", sizeof(&p));
    printf("%d\n", sizeof(&p + 1));
    printf("%d\n", sizeof(&p[0] + 1));

    printf("%d\n", strlen(p));
    printf("%d\n", strlen(p + 1));
    printf("%d\n", strlen(*p));
    printf("%d\n", strlen(p[0]));
    printf("%d\n", strlen(&p));
    printf("%d\n", strlen(&p + 1));
    printf("%d\n", strlen(&p[0] + 1));
}

参考:

void test4()
{
    char* p = "abcdef";
    
    // p指向字符串首地址,地址大小4字节
    printf("%d\n", sizeof(p)); // 4
    
    // p指向字符串首地址,加1指向下一个元素地址,地址大小4字节
    printf("%d\n", sizeof(p + 1)); // 4
    
    // p指向字符串首地址,*p取得字符串首元素,类型为char大小1字节。*p=*(p+0)=p[0]
    printf("%d\n", sizeof(*p)); // 1
    
    // 字符串首元素,类型为char大小1字节
    printf("%d\n", sizeof(p[0])); // 1
    
    // &p得到指针变量p在栈中的地址,地址大小4字节
    printf("%d\n", sizeof(&p)); // 4
    
    // &p得到指针变量p在栈中的地址,加1取得栈中p的下一个地址,类型为char**大小4字节
    printf("%d\n", sizeof(&p + 1)); // 4
    
    // 字符串首元素的地址,加1得到下一个元素的地址,类型为char*大小4字节
    printf("%d\n", sizeof(&p[0] + 1)); // 4
    
    
	// p指向字符串首地址,strlen遇到'\0'结束,得到的长度不包括'\0'
    printf("%d\n", strlen(p)); // 6
    
    // p指向字符串首地址,加1得到下一个元素的地址,即指向b
    printf("%d\n", strlen(p + 1)); // 5
    
    // p指向字符串首地址,*p取得字符串首元素a,a作为strlen的参数,将计算地址为a的ascii码值97=0x61处字符串长度,将会出现内存访问异常的错误,error
    printf("%d\n", strlen(*p)); // error
    
    // 同上,将计算地址为b的ascii码值98=0x62处字符串长度,出现内存访问异常,error
    printf("%d\n", strlen(p[0])); // error
    
    // &p得到指针变量p在栈中的地址,因'\0'位置不知,下面是一个随机数
    printf("%d\n", strlen(&p)); // 随机数,测试为3
    
    // &p得到指针变量p在栈中的地址,加1取得栈中p的下一个地址,因'\0'位置不知,下面是一个随机数
    printf("%d\n", strlen(&p + 1)); // 随机数,测试为11
    
    // 字符串首元素的地址,加1得到下一个元素的地址,即b的地址
    printf("%d\n", strlen(&p[0] + 1)); // 5
}

7.5 二维数组

void test5()
{
    int a[3][4] = { 0 };
    printf("%d\n", sizeof(a));
    printf("%d\n", sizeof(a[0][0]));
    printf("%d\n", sizeof(a[0]));
    printf("%d\n", sizeof(a[0] + 1));
    printf("%d\n", sizeof(*(a[0] + 1)));
    printf("%d\n", sizeof(a + 1));
    printf("%d\n", sizeof(*(a + 1)));
    printf("%d\n", sizeof(&a[0] + 1));
    printf("%d\n", sizeof(*(&a[0] + 1)));
    printf("%d\n", sizeof(*a));
    printf("%d\n", sizeof(a[3]));
}

参考:

void test5()
{
    int a[3][4] = { 0 };
    
    // sizeof(数组名)计算整个数组的大小 
    printf("%d\n", sizeof(a)); // 48
    
    // 二维数组a的首元素为a[0],一维数组a[0]的首元素a[0][0]类型int大小4字节
    printf("%d\n", sizeof(a[0][0])); // 4
    
    // a[0]为二维数组的首元素,也是个一维数组,类型为int[4],sizeof(数组名)得到计算整个数组的大小
    printf("%d\n", sizeof(a[0])); // 16
    
    // a[0]为一维数组,数组名表示数组首元素的地址,加1表示下一个元素的地址,等价于&a[0][0]+1,即a[0][1]的地址
    printf("%d\n", sizeof(a[0] + 1)); // 4
    
    // a[0]为一维数组,数组名为数组首元素的地址,加1得到下一个元素的地址,*得到地址对应的值,即a[0][1]处的值,类型为int大小4字节
    printf("%d\n", sizeof(*(a[0] + 1))); // 4
    
    // 二维数组名a表示数组首元素a[0]的地址,加1表示数组a下一个元素的地址,即a[1]的地址
    printf("%d\n", sizeof(a + 1)); // 4
    
    // a+1得到a[1]的地址,*得到一维数组a[1],其中有4个int型元素,sizeof(数组名)得到计算整个数组的大小。相当于sieof(a[1])
    printf("%d\n", sizeof(*(a + 1))); // 16
    
    // a[0]是一维数组,&a[0]得到整个数组的地址,加1得到越过一维数组a[0]的地址,即a[1]的地址
    printf("%d\n", sizeof(&a[0] + 1)); // 4
    
    // &a[0]+1得到a[1]的地址,*得到一维数组a[1],其中有4个int型元素,sizeof(数组名)得到计算整个数组的大小。
    printf("%d\n", sizeof(*(&a[0] + 1))); // 16
    
    // 二维数组名a表示数组首元素a[0]的地址,*得到首元素一维数组a[0],其中有4个int型元素,sizeof(数组名)得到计算整个数组的大小。*a=*(a+0)=a[0] sizeof(*a)=sizeof(a[0])
    printf("%d\n", sizeof(*a)); // 16
    
    // a[3]的类型为int[4]
    printf("%d\n", sizeof(a[3])); // 16
}

7.6 数组指针

数组指针可以接收二维数组。理解了上面的二维数组,下面的题就不是很难了,因此我就不写分析了,感兴趣的可以自己分析。

主要应用:*(arr + n) = arr[n]

void test6()
{
    int nAry[2][4] = {
        {10,20,30,40},
        {60,70,80,90}
    };

    int(*p)[4] = nAry;

    printf("%p\r\n", p);
    printf("%p\r\n", *p);
    printf("%p\r\n", (void*)**p);


    printf("%p\r\n", (void*)sizeof(p));
    printf("%p\r\n", (void*)sizeof(*p));
    printf("%p\r\n", (void*)sizeof(**p));


    printf("%p\r\n", p + 1);
    printf("%p\r\n", *p + 1);
    printf("%p\r\n", (void*)(**p + 1));


    printf("%p\r\n", p[1] + 1);

    printf("%p\r\n", (void*)*((p + 1)[1]));
    printf("%p\r\n", (void*)(*(p + 1))[1]);

    // 下标运算的优先级比*运算的优先级高
    printf("%p\r\n", (void*)(*p[1] + 1));
    printf("%p\r\n", (void*)(p[1] + 1)[1]);
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shlyyy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值