面试题详解

前言:这一期我们专门来巩固所学知识,同时见识一些面试题。对知识做出一个总结。

1 不创建临时变量交换两个整数

. 第一种方法

#include<stdio.h>
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	printf("交换前a=%d,b=%d\n", a, b);
	a = a + b;//此时a存放的不再是原来的值,而是a与b的和,意味着a的值已经被改掉了
	b = a - b;//b依然是原来的值,此时a-b相当于a+b-b就应该等于原来a的值
	a = a - b;//此时b存放的是原来a的值,a依然等于a+b的和,所以a-b就相当于a+b-a就应该等于原来b的值
	printf("交换后a=%d,b=%d", a, b);
	return 0;
}

. 第二种方法

#include<stdio.h>
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	printf("交换前a=%d,b=%d\n", a, b);
	a = a ^ b;//此时a存放的是a^b的值,a的值已经被改掉了
	b = a ^ b;//b存放的依然是原来的值,那么a^b就相当于a^b^b就等于原来a的值
	a = a ^ b;//此时b存放的是原来a的值,a^b就相当于a^b^a就等于原来b的值
	printf("交换后a=%d,b=%d\n", a, b);
	return 0;
}

这里就需要大家去自行回顾按位异或的知识了。

2 数组笔试题

. 整型数组

#include<stdio.h>
int main()
{
	//整型数组,数组大小为4,每一个元素类型都是int类型
	int a[] = { 1,2,3,4 };
	printf("%zd\n", sizeof(a));// 16
	//sizeof(a)求的是整个数组的大小,单位是字节
	printf("%zd\n", sizeof(a + 0));// 4/8
	//a作为数组名,代表首元素的地址,a+0跳过0个整型,依然指向数组首元素的地址,地址的大小与平台的大小有关
	printf("%zd\n", sizeof(*a));// 4
	//a数组名,代表数组首元素的地址,*a对a进行解引用,指向数组首元素(整型)
	printf("%zd\n", sizeof(a + 1));// 4/8
	//a数组名,代表数组首元素的地址,a+1跳过1个整型,指向下一个元素的地址,地址的大小与平台有关
	printf("%zd\n", sizeof(a[1]));// 4
	//[]下标引用操作符,a[1]访问的是下标为1的元素(整型)
	printf("%zd\n", sizeof(&a));// 4/8
	//&a取出的是整个数组的地址,地址的大小与平台有关
	printf("%zd\n", sizeof(*&a));// 16
	//*&a相当于a,sizeof(a)求的是整个数组的大小,单位是字节
	printf("%zd\n", sizeof(&a + 1));// 4/8
	//&a+1跳过整个数组,指向下一段空间的地址
	printf("%zd\n", sizeof(&a[0]));// 4/8
	//a[0]访问的是下标为0的元素,&a[0]取出的是下标为0元素的地址
	printf("%zd\n", sizeof(&a[0] + 1));// 4/8
	//&a[0]+1跳过1个整型,指向下标为1元素的地址
	return 0;
}

. 字符数组

sizeof

#include<stdio.h>
int main()
{
	//字符数组arr里是没有\0的
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%zd\n", sizeof(arr));//6
	//sizeof(arr)求的是整个数组的大小,单位是字节
	printf("%zd\n", sizeof(arr + 0));//4/8
	//arr数组名,代表数组首字符的地址,arr+0依然代表数组首字符的地址,地址大小与平台有关
	printf("%zd\n", sizeof(*arr));//1
	//*arr相当于数组首字符a,是一个字符型
	printf("%zd\n", sizeof(arr[1]));//1
	//arr[1]访问的是数组下标为1的元素,b是一个字符型
	printf("%zd\n", sizeof(&arr));//4/8
	//&arr取出的是整个数组的地址,地址的大小与平台有关
	printf("%zd\n", sizeof(&arr + 1));//4/8
	//&arr+1跳过整个数组,指向下一段空间的地址
	printf("%zd\n", sizeof(&arr[0] + 1));//4/8
	//arr[0]访问的是数组下标为0的元素,&arr[0]取出的是数组下标为0元素的地址,&arr[0]+1跳过一个字符型,指向下标为1元素的地址
	return 0;
}

strlen

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%zd\n", strlen(arr));//随机值
	//arr数组名,代表数组首字符的地址,strlen(arr)是从数组首字符的地址开始向后找\0,统计\0之前字符的个数
	printf("%zd\n", strlen(arr + 0));//随机值
	//arr数组名,代表数组首字符的地址,arr+0依然代表数组首字符的地址
	printf("%zd\n", strlen(*arr));//err
	//*arr代表数组首字符a,是一个字符型,而strlen函数的参数需要一个地址
	printf("%zd\n", strlen(arr[1]));//err
	//arr[1]访问的是数组下标为1的元素,是一个字符型
	printf("%zd\n", strlen(&arr));//随机值
	//&arr取出的是整个数组的地址,数组的地址依然是从数组首字符的地址开始访问
	printf("%zd\n", strlen(&arr + 1));//随机值-6
	//&arr+1跳过整个数组,指向下一段空间的地址
	printf("%zd\n", strlen(&arr[0] + 1));//随机值-1
	//&arr[0]取出的是数组首字符的地址,&arr[0]+1跳过一个字符型,指向数组下标为1元素的地址
	return 0;
}
#include<stdio.h>
int main()
{
	char arr[] = "abcdef";
	printf("%zd\n", sizeof(arr));//7
	//sizeof(arr)求的是数组的大小,单位是字节
	printf("%zd\n", sizeof(arr + 0));//4/8
	//arr数组名,代表数组首字符的地址,arr+0依然代表数组首字符的地址,地址的大小与平台有关
	printf("%zd\n", sizeof(*arr));//1
	//*arr代表数组首字符a,是一个字符型
	printf("%zd\n", sizeof(arr[1]));//1
	//arr[1]访问的是数组下标为1的元素,是一个字符型
	printf("%zd\n", sizeof(&arr));//4/8
	//&arr取出的整个数组的地址
	printf("%zd\n", sizeof(&arr + 1));//4/8
	//&arr+1跳过整个数组,指向下一段空间的地址
	printf("%zd\n", sizeof(&arr[0] + 1));//4/8
	//&arr[0]取出的是数组首字符的地址,&arr[0]+1跳过一个字符型,指向数组下标为1元素的地址
	return 0;
}
#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "abcdef";
	printf("%zd\n", strlen(arr));//6
	//arr数组名,代表数组首字符的地址,从这个位置开始向后找\0,统计\0之前字符的个数
	printf("%zd\n", strlen(arr + 0));//6
	//arr+0跳过0个字符型,指向数组首字符的地址
	printf("%zd\n", strlen(*arr));//err
	//*arr代表数组首字符,而strlen函数的参数需要一个地址
	printf("%zd\n", strlen(arr[1]));//err
	//arr[1]访问的是数组下标为1的元素,是一个字符型
	printf("%zd\n", strlen(&arr));//6
	//&arr取出的是整个数组的地址,数组的地址也是从数组首元素的地址开始向后访问
	printf("%zd\n", strlen(&arr + 1));//随机值
	//&arr+1跳过整个数组,指向下一段空间的地址
	printf("%zd\n", strlen(&arr[0] + 1));//5
	//&arr[0]取出的是数组首字符的地址,&arr[0]+1跳过一个字符型,指向下一个字符的地址
	return 0;
}
#include<stdio.h>
int main()
{
	char* p = "abcdef";//常量字符串,字符指针p存放的是字符串首字符a的地址
	printf("%zd\n", sizeof(p));//4/8
	//sizeof(p)求的是指针的大小,指针就是地址,与平台的大小有关
	printf("%zd\n", sizeof(p + 1));//4/8
	//p+1跳过一个字节,指向了字符串中b的地址
	printf("%zd\n", sizeof(*p));//1
	//*p就相当于a,是一个字符型
	printf("%zd\n", sizeof(p[0]));//1
	//p[0]就相当于*(p+0),访问的是字符串中的a,是一个字符型
	printf("%zd\n", sizeof(&p));//4/8
	//&p取出的是一级指针变量p的地址
	printf("%zd\n", sizeof(&p + 1));//4/8
	//&p+1跳过一个指针的大小,指向一段未知空间的地址
	printf("%zd\n", sizeof(&p[0] + 1));//4/8
	//&p[0]+1跳过一个字符型,指向下一个字符的地址
	return 0;
}
#include<stdio.h>
#include<string.h>
int main()
{
	char* p = "abcdef";
	printf("%zd\n", strlen(p));//6
	//p存放的是a的地址,strlen从这个位置开始向后统计\0之前字符的个数
	printf("%zd\n", strlen(p + 1));//5
	//p+1跳过一个字节,指向字符串中b的地址
	//printf("%zd\n", strlen(*p));//err
	//*p就相当于a,strlen函数的参数需要一个地址
	//printf("%zd\n", strlen(p[0]));//err
	//p[0]访问的是字符串中首字符a,是一个字符型
	printf("%zd\n", strlen(&p));//随机值
	//&p取出的是一级指针变量p的地址
	printf("%zd\n", strlen(&p + 1));//随机值
	//&p+1指向一段未知空间的地址
	printf("%zd\n", strlen(&p[0] + 1));//5
	//&p[0]+1跳过一个字符型,指向下一个字符的地址
	return 0;
}

. 二维数组

#include<stdio.h>
int main()
{
	int a[3][4] = { 0 };
	//二维数组,每一个元素的类型都是int
	printf("%zd\n", sizeof(a));//48
	//sizeof(a)求的是整个数组的大小,单位是字节
	printf("%zd\n", sizeof(a[0][0]));//4
	//a[0][0]访问的是数组首元素,是一个整型
	printf("%zd\n", sizeof(a[0]));//16
	//a[0]相当于二维数组第0行的数组名,sizeof(数组名)求的是整个数组的大小,单位是字节
	printf("%zd\n", sizeof(a[0] + 1));//4/8
	//a[0]代表二维数组第0行的数组名,数组名代表数组首元素的地址,a[0]+1跳过一个整型,,指向下一个元素的地址
	printf("%zd\n", sizeof(*(a[0] + 1)));//4
	//*(a[0]+1)代表的是元素,是一个整型
	printf("%zd\n", sizeof(a + 1));//4/8
	//a数组名,代表数组首元素的地址,二维数组的首元素是第0行,a+1就代表第一行的地址
	printf("%zd\n", sizeof(*(a + 1)));//16
	//*(a+1)相当于第一行的数组名,sizeof(数组名)求的是第1行数组的大小,单位是字节
	printf("%zd\n", sizeof(&a[0] + 1));//4/8
	//&a[0]取出的是第0行数组的地址,&a[0]+1跳过第0行,指向下一行的地址
	printf("%zd\n", sizeof(*(&a[0] + 1)));//16
	//*(&a[0]+1)相当于第一行的数组名,sizeof(数组名)求的是第1行数组的大小,单位是字节
	printf("%zd\n", sizeof(*a));//16
	//a数组名,代表二维数组第0行的地址,*a相当于第0行的数组名,sizeof(数组名)求的是第0行数组的大小
	printf("%zd\n", sizeof(a[3]));//16
	//a[3]相当于二维数组第2行的数组名,sizeof(数组名),求的是二维数组第2行数组的大小
	return 0;
}

3 指针笔试题

#include<stdio.h>
int main()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int* ptr = (int*)(&a + 1);
	//&a取出的整个数组的地址,&a+1跳过整个数组,指向下一段空间的地址
	//ptr是一个整型指针,ptr指向的对象是一个整型
	printf("%d,%d", *(a + 1), *(ptr - 1));//2  ,  5
	//a是数组名,代表数组首元素的地址,a+1跳过一个整型,指向下标为1元素的地址,*(a+1)访问的是数组下标为1 的元素
	//ptr-1向后跳过4个字节,指向下标为4元素的地址,*(ptr-1)访问的是数组下标为4的元素
	return 0;
}

画图分析

在这里插入图片描述


#include <stdio.h>
int main()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
	//逗号表达式,最后一个表达式的结果就是最后的结果
	//int a[3][2]={1,3,5};二维数组
	int* p;
	p = a[0];
	//a[0]代表二维数组第0行的数组名,数组名代表数组首元素的地址
	//a[0]就代表二维数组第0行数组的首元素的地址
	printf("%d", p[0]);//1
	//p[0]=*(p+0),p+0跳过0个整型,依然指向二维数组第0行数组首元素的地址
	return 0;
}
//假设环境是x86环境,程序输出的结果是啥?
#include <stdio.h>
int main()
{
	int a[5][5] = { {1,2},{2,3},{3,4},{4,5},{5,6} };
	int(*p)[4];
	//数组指针,p指向的数组大小为4
	p = a;
	//a数组名,代表二维数组第0行数组的地址
	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
	//指针-指针的绝对值代表指针之间元素的个数
	//&p[4][2]-&a[4][2]=-4
	//10000000000000000000000000000100---原码
	//11111111111111111111111111111011---反码
	//11111111111111111111111111111100---补码
	//FF  FF  FF  FC
	return 0;
}

画图分析

在这里插入图片描述


#include <stdio.h>
int main()
{
	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int* ptr1 = (int*)(&aa + 1);
	//&aa取出的是整个数组的地址,&aa+1跳过整个数组,指向下一段空间的地址
	//ptr1是一个整型指针
	int* ptr2 = (int*)(*(aa + 1));
	//aa数组名,代表二维数组首元素的地址,也就是二维数组第0行的地址
	//aa+1跳过第0行,指向第1行的地址
	//*(aa+1)相当于二维数组第1行的数组名,数组名代表首元素的地址
	//ptr2也是一个整型指针
	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
	return 0;
}

画图分析

在这里插入图片描述


#include <stdio.h>
int main()
{
	char* a[] = { "work","at","alibaba" };
	//pa是一个二级指针
	char** pa = a;
	//a数组名,代表数组首元素的地址
	pa++;
	printf("%s\n", *pa);//at
	return 0;
}

画图分析

在这里插入图片描述


#include <stdio.h>
int main()
{
	char* c[] = { "ENTER","NEW","POINT","FIRST" };
	char** cp[] = { c + 3,c + 2,c + 1,c };
	//cpp是一个三级指针
	char*** cpp = cp;
	printf("%s\n", **++cpp);//POINT
	//++cpp,cpp指向cp数组下标为1的元素c+2,c+2指向c数组下标为2的元素
	printf("%s\n", *-- * ++cpp + 3);//ER
	printf("%s\n", *cpp[-2] + 3);//ST
	//cpp[-2]=*(cpp-2)
	printf("%s\n", cpp[-1][-1] + 1);//EW
	//cpp[-1][-1]=*(*(cpp-1)-1)
	return 0;
}

画图分析

在这里插入图片描述


#include<stdio.h>
//在X86环境下
//假设结构体的⼤⼩是20个字节
//程序输出的结构是啥?
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p = (struct Test*)0x100000;
int main()
{
	//0x表示16进制数字
	printf("%p\n", p + 0x1);//0x100014
	//p是一个结构体指针,p+1就跳过一个结构体的大小(20个字节)
	printf("%p\n", (unsigned long)p + 0x1);//0x100001
	//p是一个unsigned long int,p+1执行的是整数加法,不存在跳过几个字节
	printf("%p\n", (unsigned int*)p + 0x1);//0x100004
	//p是一个unsigned int*的指针,p+1跳过一个unsigned int的大小(4个字节)
	return 0;
}

结语:今天的内容到此告一段落。制作不易,若各位有所收获,就为小编点点赞吧。

  • 21
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值