C语言进阶练习题

一.指针练习题

练习1:看图中代码,说出打印结果

下图内存中数字都是以16进制形式书写

分析:int *ptr1 = (int *)(&a + 1);,&a表示整个数组的地址,+1表示跳过整个数组后的地址,(int*)强制类型转换后赋值给ptr1,如上图所示ptr1指向数组末端。ptr1[-1]等价于*(ptr1-1),由于ptr1指针类型是int*,所以-1步长是4byte,即4个内存单元,所以指向的就是元素4,解引用就是4,%x表示以16进制形式打印,且高位不要0,所以打印结果是4

 int *ptr2 = (int *)((int)a + 1);,a表示数组首元素的地址,(int)a强制类型转换后,+1只会跳过1个字节,赋值给ptr2,如图所示ptr2指向第二个字节,由于ptr2是int*类型,解引用权限是4byte,所以从第二个字节开始往后数4byte,由于是小端存储模式,所以倒着取,结果是02 00 00 00,%x表示以16进制形式打印,且高位不要0,所以打印结果是2 00 00 00

以上是按小端存储模式来的,如果是大端存储模式,同理,结果应该是00 00 01 00,打印是100

练习2:以下代码的打印结果是

int main()
{
    int a[5][5];
    int(*p)[4];
    p = a;
    printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
    return 0;
}

图解: 

分析:&p[4][2],p是整型数组指针,类型是int (*)[4],*(p+i);(i=0;i++)会出现一个每行4个元素的重构二维数组(以下简称arr,arr相当于把数组a的结构重新排列了),a代表二维数组a的首元素地址,即第一行整个一维数组的地址,类型是int (*)[5],,所以如上图p指向首元素,p[4][2] 等价于*(*(p+4)+2),p+4就是跳过4个int[4],*(p+4)即p[4]代表arr第5行的一维数组的数组名,即arr第5行首元素地址,*(p+4)+2代表arr第5行第3个元素的地址,*(*(p+4)+2)代表arr第5行第3个元素,再&取地址即指向上图蓝色方块处。(注:实际上重构二维数组arr不会出现,只是为了好理解,想象出来的)

而&a[4][2]即数组a第5行第三个元素的地址,指向上图红色方块处。

地址-地址得到的是地址之间的元素个数,如上图红蓝之间是4个元素,但蓝是低地址,红是高地址,所以蓝-红结果是-4。

%p是以地址的16进制原码形式打印,且因为地址是没有负数的,所以会将要打印的数据的补码当成无符号数,也就是把补码当成原码打印,打印结果是FF FF FF FC

%d打印结果就是-4

练习3:看图中代码,说出打印结果

分析:*(ptr1 - 1),&a代表整个二维数组的地址,&a+1跳过整个二维数组,如图指向的位置 ,ptr1-1,即往前跳过1个整型,即10的地址。所以*(ptr1 - 1)结果就是10;

*(ptr2 - 1),a代表二维数组首元素地址,即整个第一行的地址,a+1代表整个第二行的地址,*(a+1)代表整个第二行的数组名,代表第二行首元素的地址,如上图指向位置。ptr2-1,即往前跳过一个整型,即5的地址,所以*(ptr2 - 1)结果是5

练习3:看图中代码,说出打印结果

分析:a是一个指针数组,存放的是char*类型的指针,即"work“首字符'w'的地址、"at"首字符'a'的地址,"alibaba"首字符'a'的地址。单独是数组名a代表首元素地址,即'w'的地址的地址,pa是一个二级指针,存的就是'w'的地址的地址,pa++执行一次,跳过一个char*,指向第二个char*,*pa代表第二个char*,即"at"首字符'a'的地址。

printf("%s\n", *pa);此库函数的第一个参数"%s\n"代表第二个参数需要的是地址,从此地址开始往后打印字符直至遇到'\0'截止('\0'的ASCII码值是0),这里传的参数就是"at"首字符'a'的地址,"at"后面隐藏了一个'\0',所以打印结果是at

练习4:看图中代码,说出打印结果

重点:(1)学会画图分析(2)自增自减会改变cpp自身的值(3)*cpp[-2]等价于*(*(cpp-2))

(4)操作符优先级:解引用 * > 加号+(5)常量字符串后隐藏有'\0'

二.字符串函数练习题

练习1:模拟实现strcpy函数

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
//模拟实现库函数strcpy
char* my_strcpy(char* str2 , const char* str1)
{
	char* ret = str2;
	assert(str1 && ret);
	while (*ret++ = *str1++)
	{
		;
	}
	return str2;
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[10] = { 0 };
	my_strcpy(arr2,arr1);
	printf("%s\n", arr2);
	return 0;
}

练习2:模拟实现strcat函数

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
//模拟实现库函数strcat
char* my_strcat(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest && src);
	//首先找目标字符串结尾'\0'
	while (*dest) 
	{
		dest++;
	}
	//追加
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}
int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "bit";
	my_strcat(arr1, arr2);
	printf("%s\n", arr1);
}

练习3:模拟实现strcmp函数

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1 != 0 &&*str1++ == *str2++)
	{
		//if (*str1 == 0)
		//{
		//	return 0;//相等
		//}
		//str1++;
		//str2++;
	}
	return *str1 - *str2;//不相等
}
int main()
{
	char arr1[] = "abcd";
	char arr2[] = "abcde";
	int ret = my_strcmp(arr1, arr2);
	if (ret == 0)
	{
		printf("==");
	}
	else if (ret < 0)
	{
		printf("<");
	}
	else
	{
		printf(">");
	}
	return 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值