西邮linux兴趣小组15,17,18年面试题浅析(by小羊)

*鉴于三套纳新题中考察内容的重合率较高,本篇博客从15年开始,依据知识点分类汇总。

基础知识点
  • memcpy函数:拷贝若干个字节到目标内存地址中。
  • 数据在计算机中以二进制形式存储。
  • 强制类型转换
    在这里插入图片描述

例题中的
  • 大小端
    小端字节序:数据的高字节保存在内存的高地址中,低字节保存在低地址中。(低放低,高放高)
    大端与之相反。
    我们常用的计算机,普遍为小端。

    例:15年 1.
    在内存中存储“linu”字符串时,从低地址到高地址,依次存放的是他们的ascii 码“6c” “69” “6e” “75”。当我们用%d读取它们时,会由将其转化成值为“0x756e696c”的数,即1,970,170,220‬。


  • 关键字static
    static在c语言中,主要用于定义变量或函数。
  1. 变量

    一般程序把新产生的动态数据存放在堆区,函数内部的自动变量存放在栈区。
    一般会随着函数的退出而释放空间。
    定义时会赋一个随机值。

    而静态数据(包括静态局部变量)均存放于全局数据区。
    全局数据区的数据并不会因为函数的退出而释放空间。
    此外,
    静态局部变量在程序执行到该对象的声明处时被首次初始化,而以后的函数调用不再进行初始化,如果没有显式初始化,被程序初始化为0。

  2. 函数

    静态函数与普通函数不同,它只能在声明它的文件当中可见,不能被其它文件使用。

定义静态函数的好处:
静态函数不能被其它文件所用;
其它文件中可以定义相同名字的函数,不会发生冲突。


  • sizeof与strlen函数

在计算字符串长度时,这两种函数常常会混淆。
sizeof函数返回的是整个字符串所占的存储空间(包括结尾处的’\0’)
strlen函数返回的是从所指地址开始,一直到第一个’\0’之间的长度(不包括’\0’)

例:15年 3.

char a[]="hello world";
printf("%lu,",sizeof(a));
printf("%lu",strlen(a));

输出结果为12,11


  • 数组指针 指针数组

例:15年 6.

int main(int argc, char *argv[])
{
	int a[3][4];
	printf("%p%p%p%p%p%p\n",&a[0][0],a[0],a,a[0]+1,a+1,a[1]);
	return 0;
}

若a[0][0]的地址为0x00000000,本题结果为:
0x00000000
0x00000000
0x00000000
0x00000004
0x00000010
0x00000010

其实在计算机中,不存在什么“二维数组”“三维数组”。可以把二维数组看做“元素为数组”的一维数组。即:a[3][4]是一个由3个元素组成的数组,其每个元素都是“四个元素组成的数组”。

数组名为数组首元素的地址,即:
a[0]为a[0][0]的地址,所以a[0]+1为a[0][0]的后一位,也就是a[0][1]的地址
同样,
a为a[0]的地址,所以a+1为a[1]的地址


  • 结构体内存对齐
    在系统为结构体分配存储空间时,有几个原则:
    1.内存的自然对齐:每一种数据类型,都必须放在地址中的整数倍上。
    2.总字节数为所占内存最大的数据类型的整数倍。

例:15年 7.

struct node1
{	
	int x;   	//此时,偏移值为4
	char y;     //4能整除1,偏移值为5
	double z;   //5不能整除8,向后偏移至8再存储,偏移值为16
	//16是8的整数倍
}struct node2
{	
	int x;   	//此时,偏移值为4
	double y;   //4不能整除8,向后偏移至8再存储,偏移值为16
	char z;     //16能整除1,偏移值为17
	//17不是8的整数倍,向后偏移至24
};

两个结构体分别占内存16和24个字节。

为什么存在内存对齐?
平台原因(移植原因):
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
性能原因:
数据结构(尤其是栈)应该尽可能地在自然边界上对齐。

解决方法:让占内存空间较大的数据类型先出现,占内存空间较小的后出现。


  • 宏参数的展开
    当展开宏参数时,如果宏定义式中有’#‘或’##’,则不进行宏参数的展开,
    否则,先展开参数,再展开宏。
    例:15年 8.
#define f(a,b)  a##b
#define g(a)  #a
#deine h(a)  g(a)

int main(int argc,char *argv[])
{
	printf("%s\n",h(f(1,2)));
	printf("%s\n",g(f(1,2)));
}

输出结果为 12 和 f(1,2)


  • switch语句
    switch语句中包含的命令,可以看做一座倒置的塔楼中的阶梯。
    不同的case语句,是开在侧壁不同高度的门。
    运行switch语句时,根据相应的门进入塔楼,向下行进(依次执行语句),直到运行至“break”或到达塔底,再离开。

    没有包含在任何case之后的语句,不会被执行。


  • 关键字const
    作用:限定一个变量不允许被改变,产生静态作用。
    例:15年 10.
int a=3;
const int *p1;
int const *p2;
int * const p3=&a;

其中,前两者相同,为指向常量的指针。
它们指向的内容是一个常量(即地址),可以通过改变常量(地址)中的值来改*p的值。但是不能直接通过指针来改变值。

第三行的int * const p3 ,表示p3是一个指针常量,需要显式初始化,指向一个int大小的存储空间,并且p3的值(指向的位置)不能再改变。但是可以通过*p=5这样的方式改变p所指空间的值。


  • printf函数
    printf函数的返回值为打印出的字符数。

printf函数运行时,从右到左压栈,将先读取放到栈底,后读取的放在栈顶,而从栈顶开始处理(先进后出)
即,参数从右到左依次处理。


编程题

例:15年14.

#include<stdio.h>
#include<string.h>

int main()
{
	char str[40];
	printf("请输入一个字符串:\n");
	scanf("%s",str);

	printf("一共有%d个*号\n",haha(str));

	return 0;
}


int haha(char *str)
{
	int i,j,n;
	int len;
	len=strlen(str);
	i=len-1;
	j=i;

	for(;i>=0;i--)
		if (str[i]!='*') str[j--]=str[i];
	
	n=j;

	while(j>=0)	
		str[j--]='*';

	printf("\n%s\n",str);

	return n+1;

}

例:15年15.

#include<stdio.h>

char *my_strcpy(char *str2,char *str1)
{
	int i=0;
	while(str2[i++]=str1[i]);//先赋值再判断

	return str2;
}


int main()
{
	char str1[20],str2[20];
	printf("请输入一个字符串:\n");
	scanf("%s",str1);

	my_strcpy(str2,str1);

	printf("%s\n",str2);

	return 0;
}


以上,有一些我可能表述不到位或者理解有误的,感谢指教【鞠躬

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值