Basic and Advance C Interview Preparation Guide
Sharpen your C Programming interview expertise with our handpicked 221 questions. Each question is crafted to challenge your understanding and proficiency in C Programming. Suitable for all skill levels, these questions are essential for effective preparation. Secure the free PDF to access all 221 questions and guarantee your preparation for your C Programming interview. This guide is crucial for enhancing your readiness and self-assurance.221 C Programming Questions and Answers:
1 :: What is C language?
The C programming language is a standardized programming language developed in the early 1970s by Ken Thompson and Dennis Ritchie for use on the UNIX operating system. It has since spread to many other operating systems, and is one of the most widely used programming languages. C is prized for its efficiency, and is the most popular programming language for writing system software, though it is also used for writing applications. ...
2 :: What is Duffs Device?
It's a devastatingly devious way of unrolling a loop, devised by Tom Duff while he was at Lucasfilm. In its ``classic'' form, it was used to copy bytes, and looked like this: register n = (count + 7) / 8; /* count > 0 assumed */ switch (count % 8) { case 0: do { *to = *from++; case 7: *to = *from++; case 6: *to = *from++; case 5: *to = *from++; case 4: *to = *from++; case 3: *to = *from++; case 2: *to = *from++; case 1: *to = *from++; } while (--n > 0); }
where count bytes are to be copied from the array pointed to by from to the memory location pointed to by to (which is a memory-mapped device output register, which is why to isn't incremented). It solves the problem of handling the leftover bytes (when count isn't a multiple of 8) by interleaving a switch statement with the loop which copies bytes 8 at a time. (Believe it or not, it is legal to have case labels buried within blocks nested in a switch statement like this. In his announcement of the technique to C's developers and the world, Duff noted that C's switch syntax, in particular its ``fall through'' behavior, had long been controversial, and that ``This code forms some sort of argument in that debate, but I'm not sure whether it's for or against.'')
where count bytes are to be copied from the array pointed to by from to the memory location pointed to by to (which is a memory-mapped device output register, which is why to isn't incremented). It solves the problem of handling the leftover bytes (when count isn't a multiple of 8) by interleaving a switch statement with the loop which copies bytes 8 at a time. (Believe it or not, it is legal to have case labels buried within blocks nested in a switch statement like this. In his announcement of the technique to C's developers and the world, Duff noted that C's switch syntax, in particular its ``fall through'' behavior, had long been controversial, and that ``This code forms some sort of argument in that debate, but I'm not sure whether it's for or against.'')
3 :: Here is a good puzzle: how do you write a program which produces its own source code as output?
It is actually quite difficult to write a self-reproducing program that is truly portable, due particularly to quoting and character set difficulties.
Here is a classic example (which ought to be presented on one line, although it will fix itself the first time it's run):
char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";
main(){printf(s,34,s,34);}
(This program has a few deficiencies, among other things neglecting to #include <stdio.h>, and assuming that the double-quote character " has the value 34, as it does in ASCII.)
#define q(k)main(){return!puts(#k"nq("#k")");}
q(#define q(k)main(){return!puts(#k"nq("#k")");})
Here is a classic example (which ought to be presented on one line, although it will fix itself the first time it's run):
char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";
main(){printf(s,34,s,34);}
(This program has a few deficiencies, among other things neglecting to #include <stdio.h>, and assuming that the double-quote character " has the value 34, as it does in ASCII.)
#define q(k)main(){return!puts(#k"nq("#k")");}
q(#define q(k)main(){return!puts(#k"nq("#k")");})
4 :: Suggesting that there can be 62 seconds in a minute?
Q: Why can tm_sec in the tm structure range from 0 to 61, suggesting that there can be 62 seconds in a minute?
A: That's actually a buglet in the Standard. There can be 61 seconds in a minute during a leap second. It's possible for there to be two leap seconds in a year, but it turns out that it's guaranteed that they'll never both occur in the same day (let alone the same minute).
A: That's actually a buglet in the Standard. There can be 61 seconds in a minute during a leap second. It's possible for there to be two leap seconds in a year, but it turns out that it's guaranteed that they'll never both occur in the same day (let alone the same minute).
5 :: Was 2000 a leap year?
Is (year % 4 == 0) an accurate test for leap years? (Was 2000 a leap year?)
No, it's not accurate (and yes, 2000 was a leap year). The actual rules for the present Gregorian calendar are that leap years occur every four years, but not every 100 years, except that they do occur every 400 years, after all. In C, these rules can be expressed as:
year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
Actually, if the domain of interest is limited (perhaps by the range of a time_t) such that the only century year it encompasses is 2000, the expression
(year % 4 == 0) /* 1901-2099 only */
is accurate, if less than robust.
If you trust the implementor of the C library, you can use mktime to determine whether a given year is a leap year;
Note also that the transition from the Julian to the Gregorian calendar involved deleting several days to make up for accumulated errors. (The transition was first made in Catholic countries under Pope Gregory XIII in October, 1582, and involved deleting 10 days. In the British Empire, eleven days were deleted when the Gregorian calendar was adopted in September 1752. A few countries didn't switch until the 20th century.) Calendar code which has to work for historical dates must therefore be especially careful.
No, it's not accurate (and yes, 2000 was a leap year). The actual rules for the present Gregorian calendar are that leap years occur every four years, but not every 100 years, except that they do occur every 400 years, after all. In C, these rules can be expressed as:
year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
Actually, if the domain of interest is limited (perhaps by the range of a time_t) such that the only century year it encompasses is 2000, the expression
(year % 4 == 0) /* 1901-2099 only */
is accurate, if less than robust.
If you trust the implementor of the C library, you can use mktime to determine whether a given year is a leap year;
Note also that the transition from the Julian to the Gregorian calendar involved deleting several days to make up for accumulated errors. (The transition was first made in Catholic countries under Pope Gregory XIII in October, 1582, and involved deleting 10 days. In the British Empire, eleven days were deleted when the Gregorian calendar was adopted in September 1752. A few countries didn't switch until the 20th century.) Calendar code which has to work for historical dates must therefore be especially careful.
6 :: How can I find the day of the week given the date?
Here are three methods:
1. Use mktime or localtime # . Here is a code fragment which computes the day of the week for February 29, 2000:
#include <stdio.h>
#include <time.h>
char *wday[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"};
struct tm tm;
tm.tm_mon = 2 - 1;
tm.tm_mday = 29;
tm.tm_year = 2000 - 1900;
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
tm.tm_isdst = -1;
if(mktime(&tm) != -1)
printf("%sn", wday[tm.tm_wday]);
When using mktime like this, it's usually important to set tm_isdst to -1, as shown (especially if tm_hour is 0), otherwise a daylight saving time correction could push the time past midnight into another day. # Use Zeller's congruence, which says that if
J is the number of the century [i.e. the year / 100],
K the year within the century [i.e. the year % 100],
m the month,
q the day of the month,
h the day of the week [where 1 is Sunday];
1. Use mktime or localtime # . Here is a code fragment which computes the day of the week for February 29, 2000:
#include <stdio.h>
#include <time.h>
char *wday[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"};
struct tm tm;
tm.tm_mon = 2 - 1;
tm.tm_mday = 29;
tm.tm_year = 2000 - 1900;
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
tm.tm_isdst = -1;
if(mktime(&tm) != -1)
printf("%sn", wday[tm.tm_wday]);
When using mktime like this, it's usually important to set tm_isdst to -1, as shown (especially if tm_hour is 0), otherwise a daylight saving time correction could push the time past midnight into another day. # Use Zeller's congruence, which says that if
J is the number of the century [i.e. the year / 100],
K the year within the century [i.e. the year % 100],
m the month,
q the day of the month,
h the day of the week [where 1 is Sunday];
7 :: What is hashing in C?
Hashing is the process of mapping strings to integers, usually in a relatively small range. A ``hash function'' maps a string (or some other data structure) to a bounded number (the ``hash bucket'') which can more easily be used as an index in an array, or for performing repeated comparisons. (Obviously, a mapping from a potentially huge set of strings to a small set of integers will not be unique. Any algorithm using hashing therefore has to deal with the possibility of ``collisions.'')
Many hashing functions and related algorithms have been developed; a full treatment is beyond the scope of this list. An extremely simple hash function for strings is simply to add up the values of all the characters:
unsigned hash(char *str)
{
unsigned int h = 0;
while(*str != ' ')
h += *str++;
return h % NBUCKETS;
}
A somewhat better hash function is
unsigned hash(char *str)
{
unsigned int h = 0;
while(*str != ' ')
h = (256 * h + *str++) % NBUCKETS;
return h;
}
Many hashing functions and related algorithms have been developed; a full treatment is beyond the scope of this list. An extremely simple hash function for strings is simply to add up the values of all the characters:
unsigned hash(char *str)
{
unsigned int h = 0;
while(*str != ' ')
h += *str++;
return h % NBUCKETS;
}
A somewhat better hash function is
unsigned hash(char *str)
{
unsigned int h = 0;
while(*str != ' ')
h = (256 * h + *str++) % NBUCKETS;
return h;
}
8 :: I need a sort of an approximate strcmp routine ...
I need a sort of an ``approximate'' strcmp routine, for comparing two strings for close, but not necessarily exact, equality.
Some nice information and algorithms having to do with approximate string matching, as well as a useful bibliography, can be found in Sun Wu and Udi Manber's paper ``AGREP--A Fast Approximate Pattern-Matching Tool.''
Another approach involves the ``soundex'' algorithm, which maps similar-sounding words to the same codes. Soundex was designed for discovering similar-sounding names (for telephone directory assistance, as it happens), but it can be pressed into service for processing arbitrary words.
Some nice information and algorithms having to do with approximate string matching, as well as a useful bibliography, can be found in Sun Wu and Udi Manber's paper ``AGREP--A Fast Approximate Pattern-Matching Tool.''
Another approach involves the ``soundex'' algorithm, which maps similar-sounding words to the same codes. Soundex was designed for discovering similar-sounding names (for telephone directory assistance, as it happens), but it can be pressed into service for processing arbitrary words.
9 :: What is C Programing language?
Is C++ a superset of C? What are the differences between C and C++? Can I use a C++ compiler to compile C code?
C++ was derived from C, and is largely based on it, but there are some legal C constructs which are not legal C++. Conversely, ANSI C inherited several features from C++, including prototypes and const, so neither language is really a subset or superset of the other; the two also define the meaning of some common constructs differently.
The most important feature of C++ not found in C is of course the extended structure known as a class which along with operator overloading makes object-oriented programming convenient. There are several other differences and new features: variables may be declared anywhere in a block; const variables may be true compile-time constants; structure tags are implicitly typedeffed; an & in a parameter declaration requests pass by reference; and the new and delete operators, along with per-object constructors and destructors, simplify dynamic data structure management. There are a host of mechanisms tied up with classes and object-oriented programming: inheritance, friends, virtual functions, templates, etc. (This list of C++ features is not intended to be complete; C++ programmers will notice many omissions.)
C++ was derived from C, and is largely based on it, but there are some legal C constructs which are not legal C++. Conversely, ANSI C inherited several features from C++, including prototypes and const, so neither language is really a subset or superset of the other; the two also define the meaning of some common constructs differently.
The most important feature of C++ not found in C is of course the extended structure known as a class which along with operator overloading makes object-oriented programming convenient. There are several other differences and new features: variables may be declared anywhere in a block; const variables may be true compile-time constants; structure tags are implicitly typedeffed; an & in a parameter declaration requests pass by reference; and the new and delete operators, along with per-object constructors and destructors, simplify dynamic data structure management. There are a host of mechanisms tied up with classes and object-oriented programming: inheritance, friends, virtual functions, templates, etc. (This list of C++ features is not intended to be complete; C++ programmers will notice many omissions.)
10 :: How can I call FORTRAN?
How can I call FORTRAN (C++, BASIC, Pascal, Ada, LISP) functions from C? (And vice versa?)
The answer is entirely dependent on the machine and the specific calling sequences of the various compilers in use, and may not be possible at all. Read your compiler documentation very carefully; sometimes there is a ``mixed-language programming guide,'' although the techniques for passing arguments and ensuring correct run-time startup are often arcane. Besides arranging calling sequences correctly, you may also have to conspire between the various languages to get aggregate data structures declared compatibly.
In C++, a "C" modifier in an external function declaration indicates that the function is to be called using C calling conventions. In Ada, you can use the Export and Convention pragmas, and types from the package Interfaces.C, to arrange for C-compatible calls, parameters, and data structures.
The answer is entirely dependent on the machine and the specific calling sequences of the various compilers in use, and may not be possible at all. Read your compiler documentation very carefully; sometimes there is a ``mixed-language programming guide,'' although the techniques for passing arguments and ensuring correct run-time startup are often arcane. Besides arranging calling sequences correctly, you may also have to conspire between the various languages to get aggregate data structures declared compatibly.
In C++, a "C" modifier in an external function declaration indicates that the function is to be called using C calling conventions. In Ada, you can use the Export and Convention pragmas, and types from the package Interfaces.C, to arrange for C-compatible calls, parameters, and data structures.