面试题总结
宏定义
#define 标识符 字符串
- 2019年面试题
下面代码段的输出结果是什么?输出该结果的原因是?
#define X a + b
int main(int argc, char *argv[])
{
int a = 1, b = 1;
printf("%d\n", X * X);
return 0;
}
代码相当于
int main(int argc, char *argv[])
{
int a = 1, b = 1;
printf("%d\n", (a + b) * (a + b));
return 0;
}
输出结果为: 4
在宏体中,如果宏参数前加个#,那么在宏体扩展的时候,宏参数会被扩展成字符串的形式。
- 2018年面试题
分析以下代码段,解释输出的结果。
#define YEAR 2018
#define LEVELONE(x) "XiyouLinux "#x"\n"
#define LEVELTWO(x) LEVELONE(x)
#define MULTIPLY(x,y) x*y
int main(int argc, char *argv[])
{
int x = MULTIPLY(1 + 2, 3);
printf("%d\n", x);
printf(LEVELONE(YEAR));
printf(LEVELTWO(YEAR));
}
代码相当于:
#define YEAR 2018
#define LEVELONE(x) "XiyouLinux "#x"\n"
#define LEVELTWO(x) LEVELONE(x)
#define MULTIPLY(x,y) x*y
int main(int argc, char *argv[])
{
int x = MULTIPLY(1 + 2, 3);
printf("%d\n", x);
printf("XiyouLinux YEAR\n");
printf("XiyouLinux 2018\n");
}
输出结果为:
7
XiyouLinux YEAR
XiyouLinux 2018
大小端
-
2019年
请简单叙述两种字节序(大端、小端)的概念,你的机器是什么字节序?试着写一个 C 语言程序来验证,如果你没有思路,你可以尝试着使用联合体或者指针。 -
2020年
请解释一下这行代码做了什么?
puts((char*)(int const[])
{
0X6F796958,0X6E694C75,0X72477875,
0X3270756F,0X313230,0X00000A
});
该代码输出内容为: XiyouLinuxGroup2021
假如有一个4字节的数据为 0x12 34 56 78(十进制:305419896,0x12为高字节,0x78为低字节),若将其存放于地址0x4000 8000中,则有:
内存地址 | 0x4000 8000(低地址) | 0x4000 8001 | 0x4000 8002 | 0x4000 8003(高地址) |
---|---|---|---|---|
大端模式 | 0x12(高字节) | 0x34 | 0x56 | 0x78(低字节) |
小端模式 | 0x78(低字节) | 0x56 | 0x34 | 0x12(高字节) |
明显可以看出规律,即大端“高低低高”,小端“高高低低”:
- 大端模式:是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中
- 小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中
printf和scanf
printf和scanf是最常用的输入输出函数,但你可能会不知道它们的返回值
- 2020年
下面代码的运行输出结果是什么,并说说你的理解。
int main(int argc, char *argv[])
{
char *str = "Xi You Linux Group 20";
printf("%d\n", printf(str));
return 0;
}
输出结果为: Xi You Linux Group 2021
- priintf函数的返回值为成功打印的数字或字符;
- scanf函数的返回值为成功输入的数据个数;
位移
位移问题有很多题里会遇到,位移分为算术位移和逻辑位移,在我的另一篇博客里写了算术位移和逻辑位移
static
static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量当且仅当在类初次加载时会被初始化。而非静态变量可以多次修改他的值。
- 2020年面试题
这段代码的输出结果是什么?为什么会出现这样的结果?
int i = 2;
void func()
{
if(i != 0)
{
static int m = 0;
int n = 0;
n++;
m++;
printf("m = %d, n = %d\n", m, n);
i--;
func();
}
else
{
return;
}
}
int main(int argc, char *argv[])
{
func();
return 0;
}
输出结果为:
m = 1, n = 1
m = 2, n = 1
- 2019年面试题
有如下代码段所示的函数????,当我们执行该函数时,会产生什么样的输出结
果?在同一程序中多次执行该函数,输出结果是否一致?
void f()
{
static int a = 0;
int b = 0;
printf("%d, %d\n", ++a, ++b);
return 0;
}
输出结果为:1, 1
- 2018年面试题
参考所给代码,简要地谈一谈你对 static 关键字的理解。
static int a = 2018;
static void func(void)
{
static int b;
printf("a = %d, b = %d\n", a++, ++b);
}
int main(int argc, char *argv[])
{
func( );
func( );
func( );
return 0;
}
输出结果为:
a = 2018, b = 1
a = 2019, b = 2
a = 2020, b = 3
const
- 2018年面试题
char y[]="XiyouLinuxGroup",x[]="2018";
char *const p1=y;
const char *p2=y;
p1=x; //是错的
p2=x;
*p1='x';
*p2='x'; //是错的
结构体大小
结构体中数据成员对齐规则:
1. 结构体(struct)或联合(union) 的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员的大小或该成员的子成员大小(只要该成员有子成员)的整数倍开始 。
2.结构体作为成员:如果一个结构体里有某些结构体成员,则结构体成员要从内部最大元素大小的整数倍地址开始存储。
3.收尾工作:结构体的总大小,也就是sizeof的结果,必须是内部最大成员的整数倍,不足要补齐。
struct icd
{
int a;
char b;
double c;
};
struct cdi
{
char a;
double b;
int c;
};
int main()
{
printf("%zu %zu\n",sizeof(struct icd),sizeof(struct cdi));
return 0;
}
输出结果: 16 24
数组和指针
数组和指针相似
- 2020年面试题
下面代码的运行输出结果是什么,并说说你的理解。
int main(int argc, char *argv[]) {
int a[2][2];
printf("&a=%p\t&a[0]=%p\t&a[0][0]=%p\n",&a,&a[0],&a[0][0]);
printf("&a+1=%p\t&a[0]+1=%p\t&a[0][0]+1=%p\n",&a+1,&a[0]+1, &a[0][0]+1);
return 0;
}
&a 表示了整个数组的首地址
&a[0] 表示了数组第一行的首地址
&a[0][0] 表示了数组第一个元素的地址
&a +1 表示了整个数组的下一个数组首地址&b
&a[0]+1 表示了数组第二行的首地址即&a[1]
&a[0][0]+1 表示了数组第二个元素的地址即&a[0][1]
输出结果为:
&a=0x7ffe377318a0 &a[0]=0x7ffe377318a0 &a[0][0]=0x7ffe377318a0
&a+1=0x7ffe377318b0 &a[0]+1=0x7ffe377318a8 &a[0][0]+1=0x7ffe377318a4