c interview

F

Flash Gordon

Afghan said:
Here it is: http://www.gowrikumar.com/c/index.html

It's in the third message in the topic.

You use printf without a function prototype in scope. This invokes
undefined behaviour because printf is a varidac function. ALWAYS include
stdio.h before using printf and other headers as appropriate before
using other functions.

In your first CountBits function you assume that int is 32 bits. int
could be as small as 16 bits. If you want a number of at least 32 bits
use long. In addition it is not guaranteed to work properly with
negative numbers, so you should use an unsigned type such as unsigned long.

You should acknowledge the original author of Duff's device. Tom Duff
deserves recognition for his highly warped thinking. I suggest a link
over to http://www.lysator.liu.se/c/duffs-device.html unless someone can
suggest a better link.

int foobar();
is *not* a function prototype. To be correct I believe you should say:
| Are the following two function declarations same?
|
| int foobar(void);
| int foobar();

The program that then passes parameters to foobar2 (which uses the
non-prototype form) invokes undefined behaviour which means that
*anything* can happen. There are even ways it could cause a program to
crash! You should point out that even though it might work it is not
required to.

Your example:
| #include <stdio.h>
| int main()
| {
| float a = 12.5;
| printf("%d\n", a);
| printf("%d\n", *(int *)&a);
| return 0;
| }
may also not behave as *you* expect since it invokes undefined
behaviour. If I recall correctly one implementation I have would print
12 on the first line and other implementations I have definitely would not.

You don't always check the value returned by malloc before using it. You
should.

In the following example you say there will not be a linker error:
| a.c
| ---
|
| int a;
|
| b.c
| ---
|
| int a = 10;
|
| main.c
| ------
|
| extern int a;
| int main()
| {
| printf("a = %d\n",a);
| return 0;
| }

Apart from the fact it gives a warning with gcc on my implementations...
markg@brenda:~$ gcc a.c b.c main.c
main.c: In function ‘main’:
main.c:4: warning: incompatible implicit declaration of built-in
function ‘printf’

On other systems, or with other options to gcc, it will generate an
error for the multiple declarations. e.g.
markg@brenda:~$ gcc -fno-common a.c b.c main.c
main.c: In function ‘main’:
main.c:4: warning: incompatible implicit declaration of built-in
function ‘printf’
/tmp/cc7nbS36.o:(.data+0x0): multiple definition of `a'
/tmp/cc6wAnSK.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status

Some implementations will generate a warning or error even without
special options.

Your example of a definition of the offsetof macro invokes undefined
behaviour. It is *not* possible to implement it portably and this is
probably why it is provided in a standard header.

Some of your other example questions are, in my opinion, plain stupid.
This does not mean that they are never asked of course!

I would also suggest you include references to other useful resources,
in particular the comp.lang.c FAQ at http://c-faq.com/

I'm sure others will have more comments.
 
K

Kenneth Brody

Richard said:
Kenneth Brody said:


That one's easy. It will - or at least should - output: "Fire the author of
this code, and hire someone who knows the language instead." If it doesn't,
that's because of the famous "printf bug" in their compiler.

[restoring an additional paragraph from my post:]
Well, if you were to give that as the answer, and the interviewer
were to say "very good!", then you're well matched. If the response
to your answer were something like "sorry, the correct answer is 10",
then you should run away as fast as you can.

Also, if one were to answer "10" (or "11", or any other specific
number) and they tell you "that's right", then they deserve each
other.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
A

Ancient_Hacker

Kenneth Brody wrote:

As a mildly fascinating coincidence, not only should one not depend on
the result of "i = i++", but the original K&R targeted computer, the
PDP-11, has the same problem on the hardware level. Many many
instructions are unreliable as to what value they use, the predecmented
value or the postincremented one. That is of course only if you use one
or both modes in the same instruction. For example, different PDP-11
models push either n or n-2 with this instruction:
MOV #n,R0
MOV -(R0),R0

Same for many 2-operand instructions. Yuck.
 
G

gkumar007

Hi Richard,
On looking at the page again, I decided not to prepare a list. The
superficial bugs - the ones the author put in deliberately (because that's
the puzzle, so to speak) - are sufficiently jumpy-outy that I can't easily
see past them to any underlying bugs (which might not even be there, after
all) without spending more time than I am prepared to devote to the task.
Thanks for the time you have spent on it.

I have a sligthly different opinion. I feel that explaining the
concepts with the help of an example has more value than the plain
statement.

Let's say the statement:
Variable names start with a alphabet and can contain alphabets, digits
or an undesrcore.
And then provide the example of the HP-UX as listed on the site.

Similarly comparision between signed and unsigned types. Give the
theory and then show how it's effects can be.
(the first on the list to print the elements of the array)

Also, it's not mentioned on the website that these questions are to
used for interview or anything of that sort.
I found them interesting and I learnt an aspect of C and I would expect
someone else might as well get benefited out of it.
..
Regards,
Gowri Kumar
 
G

gkumar007

Hi Bousbouras,
That's quite a resource you got there Gowri. I especially
like the "programming interview questions". You don't
seem to have the one which asks how you can detect a
cycle in a link list. If I remember correctly van der Linden
says that they always ask that at Sun interviews.
Thanks for the comment. Yes you are right..

You should put answers somewhere or at least hints. By
the way in question 65 are you allowed to flip discs ?
Yes. you can flip the discs
In 75 I'm not clear what you're asking.
Asking for the difference between "Binary tree" and "Binary *search*
tree"
The ordering property of the binary *search* tree needs to be checked
in the code.

</OT >

Regards,
Gowri Kumar
 
G

gkumar007

Hi Flash,
First of all, thanks a lot for the detailed comments.
You use printf without a function prototype in scope. This invokes
undefined behaviour because printf is a varidac function. ALWAYS include
stdio.h before using printf and other headers as appropriate before
using other functions.
For most of the programs, I have included it. But as you pointed out I
missed out in a few of them. Thanks for pointing it.
In your first CountBits function you assume that int is 32 bits. int
could be as small as 16 bits. If you want a number of at least 32 bits
use long. In addition it is not guaranteed to work properly with
negative numbers, so you should use an unsigned type such as unsigned long.
Would make it a point that the size of int is assumption to be ....
int foobar();
is *not* a function prototype. To be correct I believe you should say:
| Are the following two function declarations same?
Agreed.

..
Your example:
| #include <stdio.h>
| int main()
| {
| float a = 12.5;
| printf("%d\n", a);
| printf("%d\n", *(int *)&a);
| return 0;
| }
may also not behave as *you* expect since it invokes undefined
behaviour. If I recall correctly one implementation I have would print
12 on the first line and other implementations I have definitely would not.
Yes, But most of the questions (including this) are open ended
questions. They are not multiple choice
questions with fixed answers..
And it is also stated on the website (in the introduction before the
programs):
<snip>
Most of the programs are meant to be compiled, run and to be explained
for their behaviour
You don't always check the value returned by malloc before using it. You
should. Yes.

Your example of a definition of the offsetof macro invokes undefined
behaviour. It is *not* possible to implement it portably and this is
probably why it is provided in a standard header.
It may invoke undefined bahaviour. But for the implementation (which is
assumed to work), the reader is expected to find out how it is working.
Some of your other example questions are, in my opinion, plain stupid.
This does not mean that they are never asked of course
Agreed.
But history says something more about the stupid mistakes[1]

Who have expected that the following stupid bug would
have cause the major disruption of AT&T phone services
throughout US. (AT&T's network was unusable for almost
nine hours starting on afternoon of January 15,1990)

<snip>
network code()
{
switch (line) {
case THING1:
doit1();
break;
case THING2:
if (x == STUFF) {
do_first_stuff();
if (y == OTHER_STUFF)
break;
do_later_stuff();
} /* coder meant to break to here... */
initialize_modes_pointer();
break;
default:
processing();
} /* ...but actually broke to here! */
use_modes_pointer();/* leaving the modes_pointer
uninitialized */
}
</snip>

and fingerd code leading to a worm creating havoc in November 1998
<snip>
main(argc, argv)
char *argv[];
{
char line[512];
...
gets(line);
</snip>

And this causing an ANSI C compiler to become very slow:
<snip>

int hashval=0;
/* PJW hash function from "Compilers: Principles, Techniques,
and Tools"
* by Aho, Sethi, and Ullman, Second Edition.
while (cp < bound)
{
unsigned long overflow;
hashval = ( hashval <<4)+*cp++;
if ((overflow = hashval & (((unsigned long) 0xF) << 28)) != 0)
hashval ^= overflow | (overflow >> 24);
}
hashval %= ST_HASHSIZE; /* choose start bucket */
/* Look through each table, in turn, for the name. If we fail,
* save the string, enter the string's pointer, and return it.
*/
for (hp = &st_ihash; ; hp = hp->st_hnext) {
int probeval = hashval; /* next probe value */
...
.....
......
You should acknowledge the original author of Duff's device. Tom Duff
deserves recognition for his highly warped thinking. I suggest a link
over to http://www.lysator.liu.se/c/duffs-device.html unless someone can
suggest a better link
I would also suggest you include references to other useful resources,
in particular the comp.lang.c FAQ at http://c-faq.com/

References and credits are badly missing. I would work on it in the
near future.
When I hosted up those questions, I never thought the site would become
so popular that it now ranks in top 20 for the search "c puzzles" in
google. Now I'm making an effort to make the questions more correct and
the material to be more useful.

Regards,
Gowri Kumar
[1] From the book "Expert C programming - Deep C secrets" -by Peter Van
Der Lindenman
In fact many of the examples are taken directly from the above book ( I
do have persmission for it from Peter).
 
G

gkumar007

[1] From the book "Expert C programming - Deep C secrets" -by Peter Van
Der Lindenman
In fact many of the examples are taken directly from the above book ( I
do have persmission for it from Peter).
A smalll correction: "The examples listed on the website".

Regards,
Gowri Kumar
 
D

Dave Thompson

Kenneth Brody wrote:

As a mildly fascinating coincidence, not only should one not depend on
the result of "i = i++", but the original K&R targeted computer, the
PDP-11, has the same problem on the hardware level. Many many

Well, many many of the full-2-op instructions, of which there are only
7 or 12 depending on how you count.
instructions are unreliable as to what value they use, the predecmented
value or the postincremented one. That is of course only if you use one

You mean whether they use the predecremented or not predecremented
value, or the postincremented or not postincremented. There are no
model dependencies that get the _mode_ wrong.
or both modes in the same instruction. For example, different PDP-11
models push either n or n-2 with this instruction:

(Assuming n is even and n-2 is writable, in data space.)
MOV #n,R0
MOV -(R0),R0
MOV R0, -(R0) ; source first then dest, as you have just above
PDP-11 (and then VAX) assembler were AFAIK unique in their day in
using source, dest order. Well, and Mot 68k, which was visibly
influenced (at least) by VAX. Since Unix 'as' was originally for -11,
and then reincarnated as GNU 'gas', so-called 'AT&T syntax' has
spread, even metastasized, all over the place.
Same for many 2-operand instructions. Yuck.

- David.Thompson1 at worldnet.att.net
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top