spinoza1111 said:
...and now for something very different...
Here's a better test.
I don't think so. I thought long and hard about replying at all, but
there is enough misinformation in both the test and your answers that
at least a correction of facts should be posted.
The test is dated 1997 and uses a version of that was out of date even
then. Historical tests are fine, but this fact affects some of the
answers so the read should keep this in mind.
***** Argument coercion: Suppose your routine receives an unsigned
long as its argument, but you
***** need to use it as an integer. How would you coerce it?
If safety is not a concern I would use "coercion" aka "casting" as in
(int)ulngValue. If safety is a concern I would test the coercion like
this:
intValue = (int)ulngValue;
If the conversion is unsafe the game is up when you do this.
if ((unsigned long)intValue != ulngValue) printf("Error\n");
You should test against the int type's limits:
if (ulngValue > INT_MAX) /* report a problem... */
***** Sending functions as arguments: Suppose your routine receives a
pointer to a function as its
***** first argument, as in the example
***** routine (foo, n);
***** int foo ();
***** int n;
***** { ... code ... }
There is a syntax error in the question.
***** How will the code invoke that function, passing it the integer
value as its single argument?
(*fooInstance)(n); // Don't know if this is right. Have added possibly
redundant parentheses.
(The name is wrong, but if you use * the parentheses are not
redundant. *foo(n); is entirely different to (*foo)(n)

.
The age of language being discussed matters here. My guess is that
the expected answer is
(*foo)(n);
For nearly 20 years another, possibly better, answer has been
foo(n);
and anyone learning C now should remember that both work and mean the
same thing.
***** Declarations and typedefs
***** How would you define a type num_ptr, that is a pointer to an
integer?
typedef num_ptr int *;
typedef int *num_ptr;
***** How would you define a type num_array, that is a pointer to an
array of 100 integers?
typedef num_array int[100] *;
typedef int (*num_array)[100];
Note: this is an unusual type in C and I suspect that the test author
did no mean to ask for it, but who can tell?
***** How would you define a type complex, that is a structure for a
complex number (containing two
***** part, real and imag, each of which is a double)?
struct complex
{
double realPart;
double imagPart;
} [instance name is optional here if you want to declare an instance
here] ;
typedef struct complex { double real, imag; } complex;
***** Forward declarations: Under what circumstances do you need to
make a forward declaration of a
***** function? Any other data type?
You need to do a FD when a function refers to another function in the
same compilation unit, and for some sillyass reason the function
implementation needs to follow the reference. Unlike many decent
languages, C requires the programmer to define all symbols before they
are used; this in itself shows that C is an antique, since memory in
older machines was at a premium. If the text of the function follows
its use, the header of the function must be coded as a semicolon-
terminated C statement before the first use. This is because the
correct parsing of a function use requires knowledge of its
declaration, as in the case of a function with a variable number of
arguments.
Given the age of the C being discussed, a lot of this answer is wrong
(some of it is wrong about modern C as well) and a correct answer
would be of only historical interest.
***** C declarators: Typedefs and declarations are two instances of C
statements that
***** use "declarators"; typecasts also do. What is x, according to
each of the following
***** declarators?
int *x; a pointer to an integer
int *x(); a pointer to a function that returns an integer
a function returning a pointer to int
int **x; a pointer to a pointer to an integer
int **x(); a pointer to a pointer to a function that returns an
integer
a function returning a pointer to pointer to int
int *x[10](); a pointer to a function that returns an array of ten
integers
In this case the type of x is not a valid C type. Literally
transcribed it is "and array of 10 functions returning poiter to int"
but this is not allowed in either C90 or C99. Of the test is about
K&R C and I had to go check to see if there was a special rule about
this type in old C. There isn't. It was not valid in K&R C either.
***** (Hint: don't be too sure you know, unless you are aware of the
so-called right-left rule for C ***** declarators.) If you're really
confident, what is
int *(*(*(*x)()) [10]) ();
I don't have the confidence to figure this one out. As code it sucks.
Yes, it's a silly type: "a pointer to function returning pointer to array
of 10 pointers to functions return pointer to int" (I think).
But you know that.
Skipped.
***** This is from Harbison/Steele, p. 83.
***** Structures and unions
***** Structure names: Is it wrong for a to appear twice in this
declaration? Explain
***** struct a {int num1, num2;} a;
No, since the structure name a is prefixed when it is used by
"struct". C knows that "a" is a structure when it is used as a
structure because it must be prefixed by "struct". Of course, it is
very poor practice to do this. Disciplined use of Hungarian notation
(TYP for the structure, USR for a structure instance) avoids this.
Anyone learning c should know that this latter opinion is not
universally held.
***** Padding of structures: Why is the size of the following two
structures different? How would
***** you prove it?
It would be better to ask why might they be different since they don't
have to be. In fact, I guess the are quite often are the same size (they
are on my current laptop).
***** struct y {double big;
***** float med; int small;
***** char tiny; char tiny2};
There is a syntax error in this question as well.
***** struct z {double big;
***** char tiny; float med;
***** char tiny2; int small;};
The sizes are different because in the second, "med" is aligned on a
word (32 bit) boundary, resulting in three extra pad bytes after tiny,
and small is aligned on a halfword binary, resulting in an extra byte
after tiny2.
Prove it by coding and running this:
struct y yInstance;
struct z zInstance;
printf("Struct y len=%d: struct z len=%d\n", &(structyInstance.tiny2)
+ sizeof(char) - &yInstance,&(structzInstance.small) + sizeof(int) -
&yInstance);
There are too many typos to know what was intended here but it is
overly complex. If the typos are just in the variable names, then n
the code in undefined unless there is are one or #defines in effect
that fix the problems.
A simpler solution is:
printf("struct y and struct z are%s the same size.\n",
sizeof(struct y) == sizeof(struct z) ? "" : " not");