Interesting C Interview Questions and Answers
thegeekstuff.com
thegeekstuff.com
Question 12 is even worse, as the processing order is implementation defined. On my compiler, it prints out 60..40..60.
C questions should be designed to show whether or not the candidate can write robust, professional quality code, not to test esoteric knowledge that even the interviewer can't get right.
I was asked questions like these in an interview once. It was such a massive red flag to me that I went with another company (the final straw was arguing over the size of int, which he insisted was always 32 bits).
Sure, it can be important to know what these problems are and how to identify them if you should have to read through some terrible code written by someone else. Still, I think the author goes a bit far; it should be more important that you hire a programmer who doesn't produce this sort of code in the first place.
In the end I think there is no "best way" to technically test programmers; you're better off covering as many bases as possible with a bit of programming, a bit of documentation/explanation, some debugging, etc.
strncpy(argv[0], "NewName", 7);
WTF does 7 come from, the source or the destination?As the comments said, argv[0] does not have to point to writable memory, because argc can be 0. In this case argv[0] is supposed to be NULL, which would segfault the program.
If you had to solve this question (it would be better not to ask it, because you don't learn much), I think the solution:
argv[0] = "NewName";
would be better. It's at least shorter. int main()
{
char *args[] = { 0 };
execve("./zero", args, 0L);
}
zero will have argc == 0.Certainly on all real-world platforms with a conforming main() implementation (i.e. there are some embedded systems which have stubbed mains, or just use something like _start directly) argv is passed on the stack and is writable.
Also, while argv itself may be passed on the stack, the memory each entry of argv points to is not.
But once again, we're arguing esoteric edge cases that have no place in an interview, let alone in professional code.
And the bit about argv not being passed on the stack is simply wrong on all real platforms. The argv[] array of pointers and the memory they point to is absolutely on the stack at process start.
5.1.2.2.1 Program Startup: "The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination."
However, nothing says they must be on the stack. I ran the following program to test this:
int main(int argc, const char * argv[])
{
char buff1[0x1000];
char buff2[0x1000];
printf("buff1 = %p\n", buff1);
printf("buff2 = %p\n", buff2);
printf("argv = %p\n", argv);
for(int i = 0; i < argc; i++)
{
printf("arg %d = %p\n", i, argv[i]);
}
return 0;
}
I passed it the params "1 2 3" and got the following: buff1 = 0x7fff5fbfe7b0
buff2 = 0x7fff5fbfd7b0
argv = 0x7fff5fbff7f8
arg 0 = 0x7fff5fbff970
arg 1 = 0x7fff5fbff9e9
arg 2 = 0x7fff5fbff9eb
arg 3 = 0x7fff5fbff9ed
It seems odd that there's a 376 byte gap between what's clearly the stack and what addresses the arguments reside at. They also appear in ascending order despite the fact that the stack is descending (a required convention, maybe?). It's still pretty damn close to the stack so it might very well be the stack with a bunch of process-specific stuff in it, or it could just be that the OS put the start of the stack close to the startup parameters.Either way, this is very esoteric stuff that has no place in an interview. I've read through the complete spec a number of times and I STILL get stuff wrong!
Well this is always true, so I guess that means there's no such thing as memory leaks in C. Checkmate garbage collectors.
To illustrate the difference, I wrote two quick programs.
This one has memory that the OS can recover:
#include <stdlib.h>
int main(void) {
char *a = malloc(10);
return 0;
}
This one has memory that the OS cannot recover: #include <stdlib.h>
int main(void) {
char *a = malloc(10);
a = malloc(10);
return 0;
}No, that's not how it works....
/sarcasm
When a process allocates memory, the kernel doesn't give it a physical memory address. It gives it a virtual address, which, when accessed, will be mapped to some physical address. The kernel has to keep track of which virtual addresses map to which physical addresses for each process, and it stores these mappings in a data structure called a "page table". At all times, the kernel knows what memory segments are in use by a given process.
So, when a process exits, the kernel can just look at its page table to see what memory had been allocated to it. Provided that no other processes shared the same memory, it can free it.
An actual memory leak is when the amount of memory program allocates grows with runtime while the amount of data the program is processing remains the same.
Depends on what you are studying. While I never had any specific "learn C" courses it is by far the most used language in other courses (OS programming, parallel programming, compiler construction, network programming, micro-controllers, graphics and game programming, security courses etc.). No other language comes close (a lot of the time a C++ compiler is used but the C subset is what ultimately has been used).
#3 notes a warning for main not returning int, but doesn't point out that without stdlib.h, malloc() and free() will be declared implicitly with incorrect types. (Edit: this produces a warning on 4.7 GCC and Clang 3.0.)
Almost all of these questions have something wrong with them other than what the author is pointing out. I question the author's familiarity with C.
This makes me wonder if anyone ever did a compiler where malloc returned a segment + offset (I think that gives a 48 bit pointer) for a 386 class machine.
The G choice was always "No, looks good".
It's timed.