9个面试必备问题 *
Toptal sourced essential questions that the best C developers and engineers can answer. Driven from our community, we encourage experts to submit questions and offer feedback.
现在就雇佣一名顶级C开发人员面试问题
A void pointer is a pointer that can be used to point to any data of any arbitrary type. A void pointer can be dereferenced only after explicit casting. 例如:
Int a = 5;
void *b = &a;
printf (" % d \ n”* ((int *) b));
The difference lies in where the preprocessor looks for the file to be included. For the include
指令,文件名带双引号, the preprocessor limits its search for the file to the same directory where the current source file resides, and then to the standard directories pre-designated by the compiler. 另一方面, 当指令使用尖括号时, the preprocessor searches for the file in directories pre-designated by the compiler - usually directories where standard library header files reside.
Dangling pointers are those that point to memory locations which have already been freed. 例如:
Int *a = malloc(sizeof(Int));
free(a);
// a现在是一个悬空指针
Memory leaks are quite the opposite of dangling pointers. Memory leaks happen when memory locations are not freed, but there is no way to refer to them (i.e.,没有指针指向它们).
Int *a = malloc(sizeof(Int));
a = 0;
// now a no longer points to the memory that we just allocated, causing a memory leak
与带有垃圾收集器的高级语言不同, it is critical to always keep track of allocated memory when programming in C.
申请加入Toptal的发展网络
并享受可靠、稳定、远程 自由C语言开发者职位
上面的语句声明 x
as a pointer to a function that takes a single character-pointer argument, and returns a character.
What will be the output when the following code is executed? Explain.
#include
#define SQUARE(a) (a)*(a)
Int main() {
printf (" % d \ n”,平方(4));
Int x = 3;
printf (" % d \ n”,广场(+ + x));
}
答案是事实 undefined,并取决于所使用的编译器. 一些编译器会导致 16
and 20
,而其他人则会生产 16
and 25
.
人们可能会期待第二次使用 SQUARE
宏观收益 16
,就像第一次使用的 SQUARE
macro. However, 宏由预处理器处理, a step that takes place before actual compilation begins. Expanding the second macro will show what actually gets compiled:
(++x)*(++x)
预增量操作的求值 ++x
C语言中的未定义行为是从哪里来的. 对于某些编译器,宏将减少为 (4)*(5)
,而在其他情况下,它将被计算为 (5)*(5)
.
这篇文章 进一步讨论这种行为.
这个函数 gets()
从 stdin
并将它们存储在提供的输入缓冲区中. However, gets()
will keep reading until it encounters a newline character. Unless the buffer is large enough, or the length of the line being read is known ahead of time, gets()
can potentially overflow the input buffer and start overwriting memory it is not supposed to, 造成严重破坏或打开安全漏洞.
解决这个问题的一种方法是使用 fgets()
. It allows you to put a limit on the maximum number of characters to read:
Fgets (b, 124, stdin);
A struct is a complex data type that allows multiple variables to be stored in a group at a named block of memory. Each member variable of a struct can store different data, and they all can be used at once.
Struct a {
int x;
char y;
} a;
例如,您可以将一个整数存储在 x
,和和一个字符 y
以上,相互独立.
A union, 另一方面, stores the contents of any member variable at the exact same memory location. This allows the storage of different types of data at the same memory location. The result is that assigning a value to one member will change the value of all the other members. Unlike struct, only one member of the union type is likely to be useful at any given time.
联盟b {
int x;
char y;
} b;
例如,将字符存储在 y
可能会自动更改读取的整数 x
对无意义或不可预测的事物.
This code snippet converts a floating point number to an integer using casting:
浮动f = 1.0;
Int i1 = (Int) f;
Int i2 = * (Int *) &f;
printf (" % d \ n, i1);
printf (" % d \ n, i2);
输出结果如下:
1
1065353216
你能解释一下为什么结果不同吗?
The first casting operation properly converts from a floating point number to an integer, 由C标准指定. 第二次转换, however, is first casting a float pointer to an integer pointer which is then dereferenced to get the final result. This way the compiler is effectively treating raw bits from a float (typically stored in IEEE floating point format) as if they were bits of an integer. Besides getting a wrong result you are potentially doing a “bad read” operation, in cases where sizeof (int)
大于 sizeof(浮动)
(e.g. 在某些64位架构上).
尽管这种特殊的代码不太可能, it demonstrates one of the risks involved in typecasting when only a pointer to the variable to be cast is available. 实际上,指针必须解引用 before 它是铸造的.
What is the output of the following program if run on a 32-bit operating system?
#include
int main ()
{
int a=-2;
printf("%x",a>>3);
}
In a 32 bit operating system, integers are stored as 4 bytes.
Since a
是负的,它会存储在2的补码中吗. When an integer is negative and we want to right shift by “n” bits, 我们需要在前面加上1(而不是0)!)到左手边. 因此,答案是 0xFFFF
(%x
输出十六进制的值).
There is more to interviewing than tricky technical questions, 所以这些只是作为一个指南. Not every “A” candidate worth hiring will be able to answer them all, nor does answering them all guarantee an “A” candidate. 一天结束的时候, 招聘仍然是一门艺术,一门科学,需要大量的工作.
为什么Toptal
提出面试问题
Submitted questions and answers are subject to review and editing, 并可能会或可能不会选择张贴, 由Toptal全权决定, LLC.
寻找C开发人员?
寻找 C开发人员? 查看Toptal的C开发人员.
菲比召唤
Phoebe is a full-stack developer with over nine years of experience building software across a range of industries and company sizes. 她的主要关注点是服务器端开发, 但她也喜欢使用现代UI解决方案. 菲比对她的代码一丝不苟, 热心倡导最佳实践, and knows how fundamental communication is in delivering exceptional products.
Show More尼古拉Vasović
As a software engineering master's graduate and the holder of a prestigious national scholarship, Nikola kickstarted his full-stack developer career at Toptal. Leveraging expertise in Flutter for cross-platform mobile development, he specialized in streamlining MVP product launches for startups. Nikola co-founded and acted as the CTO of Varius Development and extended his DevOps and PM expertise while collaborating with prominent global enterprises, 转变为多才多艺的IT专业人士.
Show MoreToptal连接 Top 3% 世界各地的自由职业人才.
加入Toptal社区.