【校招面经】“学完C语言” · 这些高频面试考点你都掌握了吧~

简介: 学完C语言 · 这些高频面试考点你都掌握了吧~

目录

一、大小端字节序

1.大小端引入

2.何为大端小端

3.百度真题

思路

代码执行

4.作业补充

二、深入理解static关键字

1.static修饰局部变量

2. static修饰全局变量

3.static修饰函数

三、深剖const关键字

1.const修饰变量

2.常变量可成为数组一部分吗?

3.const修饰指针

四、手写求字符串长度函数(strlen)

1.方法一:普通解法

2.方法二:递归法

3.方法三:指针 - 指针

五、手写字符串拷贝函数(strcpy)

六、遇见安然遇见你,不负代码不负卿!


【前言】

为了考察自己对于C语言掌握情况,我特意在论坛里面整理了近百份C/C++研发方向的面经,我发现有很多知识点频繁被考察,下面我将这些高频考点分享给大家,铁汁们看看自己能答对多少个。(顺便说一下哈,C语言内容其实是非常多的,这里所说的“学完C语言”,指的仅仅是学完C语法而已)

【声明】

下面所总结的内容可能并不是面面俱到的,后续还会有所补充。

【注意】:博主刚建立了一个社区和QQ学习群,链接和二维码在最下面哦,非常欢迎铁汁们的加入!

 

一、大小端字节序

1.大小端引入

看看下面这段代码:

#include<stdio.h>
int main()
{
  int a = 0x11223344;//以十六进制的形式赋值给a
  return 0;
}

很明显,在内存中存储的顺序不对呀,这是为什么?这里就要介绍大小端了。

2.何为大端小端

大端字节序存储:

当一个数据的低位放到高地址处,数据的高位放到低地址处;

小端字节序存储:

当一个数据的低位放到低地址处,数据的高位放到高地址处

比如上面的栗子:

3.百度真题

下面看看15年百度的一道价值10分的笔试题!

百度2015年系统工程师笔试题(10分):

请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。

概念的话都在上面啦,请看看如何设计小程序来判断...

思路

可以定义一个整型变量,并且初始化为1,所以它转换成十六进制表示形式就是0x00 00 00 01如果当前机器是小端字节序存储,那么从低地址到高地址就是01  00 00 00;如果当前机器是大端字节序存储,那么从低地址到高地址就是00 00 00  01;所以不同点就在于低地址处一个是01,一个是00,那怎么去判断呢?这里就可以使用前面指针所学的解引用操作,不过对于整型指针来说一次访问4个字节,而我们想要的仅仅读取到1个字节即可。所以这里就需要进行强制类型转换,将int* 转换成char* 类型的,这样的话进行指针解引用操作的时候,一次就只能访问一个字节的内容了。

分析起来很简单,下面看看代码该如何编写:

代码执行

#include<stdio.h>
int main()
{
  int a = 1;//00 00 00 01
  char* p = (char*)&a;
  if (1 == *p)
  {
    printf("小端\n");
  }
  else
  {
    printf("大端\n");
  }
  return 0;
}

上面这段代码只是方便大家理解,实际上我们交给面试官看的话,这么写代码就显得很low啦,所以下面才是满分答案:

#include<stdio.h>
int check_sys()
{
  int a = 1;//0x00 00 00 01
  return (*(char*)&a);//返回0-大端;返回1-小端
}
int main()
{
  int ret = check_sys();
  if (1 == ret)
  {
    printf("小端\n");
  }
  else
  {
    printf("大端\n");
  }
  return 0;
}

4.作业补充

unsigned int a = 0x1234;
unsigned char b = &a;
在32位大端式处理器变量b 等于()
A:0x00
B:0x12
C:0x34
D:0x1234
//很明显,答案是A,因为实际上a中放的是0x00001234

问:字符类型有大小端字节序问题吗?

答:没有,因为字符类型只有一个字节,何来字节序一说呢。


二、深入理解static关键字

在我整理百份面经后,我发现,static、extern、const、struct等关键字是大多数公司考察的重点,考的相当频繁,其中不乏知名大厂!

下面详细介绍static关键字:

static —— “静态”之意

C语言中static是用来修饰变量和函数的。

  • 修饰局部变量——静态局部变量
  • 修饰全局变量——静态全局变量
  • 修饰函数——静态函数

1.static修饰局部变量

//代码1
#include<stdio.h>
void test()
{
  int a = 1;//局部变量a的作用域在test()中,当a出了作用域就被销毁了,下次调用test()时,又需要重新创建a
  a++;
  printf("%d ", a);
}
int main()
{
  int i = 0;
  for (i = 0; i < 10; i++)
  {
    test();
  }
  return 0;
}

//代码2
#include<stdio.h>
void test()
{
  //static修饰局部变量a
  static int a = 1;
  a++;
  printf("%d ",a);
}
int main()
{
  int i = 0;
  for (i = 0; i < 10; i++)
  {
    test();
  }
  return 0;
}

看:上面的两块代码几乎一样,只不过第二个代码中自定义函数test()里面用static修饰局部变量,所以出现了这样的差异。


根据代码2的结果推测出每一次调用test(),使用的a都是上一次函数调用时留下的a;第二次调用test()时,由于上次函数调用产生的a没有被销毁,所以不会再次创建a,直接跳到了下一步,a++


【敲黑板】:

static修饰局部变量的时候,其实是改变了变量的存储类型,由栈区存储变成了静态区存储,从而使得静态的局部变量出了自己的作用域也不会被销毁,其实也就是相当于改变了这个变量的生命周期。

这里补充一条小知识点:

内存是一块比较大的空间,在使用内存的时候,会划分出不同的功能区域:栈区、堆区、静态区(这里为了好理解就直接这样说了,后面会详细介绍到这块内容)

2. static修饰全局变量

//代码1
//add.c文件
int g_val = 2018;//g_val是在add.c文件中定义的全局变量
//test.c文件
//如果想使用来自其他文件(外部文件)的全局变量,要先声明一下
extern int g_val;
//extern是一个关键字,专门用来声明外部符号的
int main()
{
  printf("%d\n", g_val);
  return 0;
}

上面这个程序是正常编译的,不过下面的这个程序就不行了哦

/代码2
//add.c文件
static int g_val = 2018;
//test.c文件
extern int g_val;
int main()
{
  printf("%d\n", g_val);
  return 0;
}

第二个程序编译的时候会报错,因为出现连接性错误。

【解释】

一个全局变量在整个工程中的其他子文件内部能被使用,是因为全局变量具有外部链接属性什么叫外部链接属性,一个变量在一个文件中定义,但是在另一个文件中可以使用(访问)叫外部链接属性当一个全局变量被static修饰的时候。其外部链接属性就变成了内部连接属性;使得这个全局变量只能在自己的源文件内部使用,其他文件不能再使用,因为它不再具有外部链接属性,给我们的感觉是作用域变小了。另外,局部变量只有内部链接属性

3.static修饰函数

//代码1
//add.c文件
int Add(int x, int y)
{
  return x + y;
}
//test.c文件
extern int Add(int x, int y);
int main()
{
  printf("%d\n", Add(2, 3));
  return 0;
}

上面的程序编译正常,但是下面的程序编译时会出现错误哦。

//代码2
//add.c文件
static int Add(int x, int y)
{
  return x + y;
}
//test.c文件
extern int Add(int x, int y);
int main()
{
  printf("%d\n", Add(2, 3));
  return 0;
}

这个程序编译时出现连接性错误。

因为函数本身就具有外部链接属性,static修饰函数的时候,函数本来是具有外部链接属性的,但是被static修饰后,就变成了内部连接属性,导致这个函数只能在自己的源文件内部使用,给我们的感觉是改变了作用域。


三、深剖const关键字

1.const修饰变量

【注意】:const修饰的只读变量不可直接被修改

//const修饰的只读变量不可以直接被修改
const int a = 10;
a = 20;//错误

问:const修饰的变量真的不能被修改吗?

其实const修饰的变量可以被间接修改掉

//const修饰的变量可以间接被修改
const int i = 10;
int* p = &i;
*p = 20;
printf("%d\n", i);//打印20

这样的话就有一个问题:const修饰变量意义何在?

  1. 让编译器进行直接修改式检查;
  2. 告诉其他程序猿(正在修改你代码的或者阅读你代码的)这个变量后面不要改哦,也属于一种”自描述”含义

2.常变量可成为数组一部分吗?

const int n = 10;
int arr[n] = {0};


注意,上面的代码在VS编译器(标准C)下直接报错了,但在gcc(GNU扩展)下可以正常编译,所以我们一切都要向标准看齐,这样的话,也就是不可以!上面的定义是错误的。

3.const修饰指针

面试题:const* 和 *const 什么区别?

const修饰指针的时候(有两种):


const放在*的左边(const int* p) ,修饰的是*p,使得*p不能改变(保证指针指向的内容不能通过指针修改),但是指针变量p本身可以改变;


const放在*的右边(int* const p),修饰的是p,使得p 不能改变。但是*p可以被修改

题目描述:

下列选项中哪一种形式声明了一个指向char类型变量的指针P,P的值是不可修改的,但P指向的变量的值是可以修改的?C

A:const char* p;//const修饰*p
B:char const* p;//const修饰*p
C:char* const p;//const修饰p
D:const char* const p;//const既修饰*p,又修饰p

思路:其实一看到题目中说p的值是不可修改的我们就应该想到const放在*的右边。


四、手写求字符串长度函数(strlen)

库函数strlen()原型:

1.方法一:普通解法

//方法一:普通方法
int my_strlen(const char* str)
{
    assert(str);//最好加上断言
  int count = 0;
  while (*str++)
  {
    count;
  }
  return count;
}

2.方法二:递归法

int my_strlen(const char* str)
{
  //找重复:my_strlen(str+1)是原问题的重复
  //找边界
  if (*str == '\0')
  {
    return 0;
  }
  return my_strlen(str + 1) + 1;
}

3.方法三:指针 - 指针

//方法三:指针 - 指针
int my_strlen(const char* str)
{
    assert(str);//最好加上断言
  char* end = str;
  while (end++)
  {
    ;
  }
  return end - str;
}

五、手写字符串拷贝函数(strcpy)

//本题需要注意的有两点:
//一是str1要足够大
//二是要保存str1的首地址
char* my_strcpy(char* str1, const char* str2)
{
  assert(str1 && str2);//最好加上断言
  char* ret = str1;//注意哦,记得保存str1的首地址
  while (*str1++ = *str2++)
  {
    ;
  }
  return ret;
}

【敲黑板】:本题需要注意的有两点:

  1. str1要足够大
  2. 保存str1的首地址

六、遇见安然遇见你,不负代码不负卿!

今天暂且到这里咯,后续会持续更新的哈,目标大厂,从最基本的知识点做起!

    如果有所收获,求求来个三连吧~

博主昨天刚建立了一个社区,非常欢迎铁汁们的加入并同步自己的博文到社区里引流,后面我也会在社区里开展一些奖励活动的哟,快来join us!

【招贤纳士】:建立初期,希望大家各显神通,表现积极优秀的童鞋可以搭伙一同管理社区!

image.png

最近由于我忙着复习备战期末考试,所以有很多铁汁给我的私信都没有及时回复,实在是对不起,所以我建立了一个QQ群,里面有很多资料,包括C/C++研发方向、Java研发方向的书籍,还有许多算法书,欢迎大家加入,如果有问题可以发到群里面,我们一同探讨,总之一句话,拒绝躺平,冲刺大厂!

QQ群号:926297014


相关文章
|
1月前
|
网络协议 编译器 Linux
【C语言】结构体内存对齐:热门面试话题
【C语言】结构体内存对齐:热门面试话题
|
18天前
|
Java 程序员
面试高频考点!关于构造方法的那些事儿
本文介绍了Java中的构造方法,包括其基本概念、默认构造方法、构造方法的重载、构造方法的细节以及执行顺序。通过具体示例,详细解释了构造方法在对象初始化中的重要作用,帮助读者在面试中更好地应对相关问题。
24 1
|
1月前
|
Java 程序员
Java 面试高频考点:static 和 final 深度剖析
本文介绍了 Java 中的 `static` 和 `final` 关键字。`static` 修饰的属性和方法属于类而非对象,所有实例共享;`final` 用于变量、方法和类,确保其不可修改或继承。两者结合可用于定义常量。文章通过具体示例详细解析了它们的用法和应用场景。
28 3
|
5月前
|
存储 安全 编译器
C语言面试题1-10
指针声明后立即初始化。 内存释放后将指针置为NULL。 避免越界访问。 10. 一个指针变量占几个字节? 一个指针变量的大小与系统和编译器相关。在32位系统中,指针变量占4个字节;在64位系统中,指针变量占8个字节。 通过深入了解以上问题,能够更好地掌握C语言内存管理的核心概念,提高编写高效、安全代码的能力。
55 1
|
1月前
|
Serverless 编译器 C语言
【C语言】指针篇- 深度解析Sizeof和Strlen:热门面试题探究(5/5)
【C语言】指针篇- 深度解析Sizeof和Strlen:热门面试题探究(5/5)
|
3月前
|
C语言
C语言操作符(补充+面试)
C语言操作符(补充+面试)
45 6
|
3月前
|
算法 C语言
【面试题】【C语言】寻找两个正序数组的中位数
【面试题】【C语言】寻找两个正序数组的中位数
30 0
|
5月前
|
存储 安全 编译器
C语言面试题11至20题
在C语言中,可以使用以下方式实现循环: for循环:用于确定次数的循环。 for (int i = 0; i < 10; i++) { // 循环体 } while循环:用于条件控制的循环。 while (condition) { // 循环体 } do-while循环:至少执行一次的条件循环。 do { // 循环体 } while (condition); 通过深入理解这些面试题,可以更好地准备编程面试,展示对编程原理和技术细节的深刻掌握。
48 3
|
5月前
|
存储 缓存 C语言
C语言面试题30至39题
. 用变量a给出下面的定义 由于题目未明确定义,这里给出几个常见定义: 整数变量:int a; 字符变量:char a; 浮点变量:float a; 双精度浮点变量:double a; 指针变量:int *a; 通过理解和掌握这些面试题,可以更好地准备编程面试,展示对编程原理和技术细节的深刻掌握。
47 2
|
6月前
|
存储 算法 C语言
从C语言到C++_39(C++笔试面试题)next_permutation刷力扣
从C语言到C++_39(C++笔试面试题)next_permutation刷力扣
61 5