Re: Another spinoza challenge
- From: Ben Bacarisse <ben.usenet@xxxxxxxxx>
- Date: Tue, 25 Aug 2009 01:10:07 +0100
spinoza1111 <spinoza1111@xxxxxxxxx> writes:
<snip>
...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.
<snip>
http://web.engr.oregonstate.edu/~pancake/cs551/Ctest.html
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.
<snip>
***** 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<snip>
***** 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<snip one possible layout>
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");
***** Unions: What is the difference between the definition for y
above, and this one?
***** union y {double big;
***** float med; int small;
***** char tiny; char tiny2};
big, med, small, tiny and tiny2 all start at the same address in the
union, whereas they follow each other in the corresponding struct
***** How big is the union, in bytes?
It is eight bytes wide
***** Preprocessing features
***** Macros versus functions: Why is a macro preferable to a function
for simple operations?
A macro is preferable because it is replaced by inline code, with no
overhead for a subroutine call to code anywhere else.
***** Under what circumstances is it necessary to use a function
rather than a macro?
In most circumstances: (1) the code to be implemented may be large,
and for this reason it would cost too much storage to use a macro for
inline expansion, (2) the function may need for clarity to be strongly
typed such that the type of parameters should be checked at compile
time: (3) complex functionality is tricky to implement in macros: (4)
complex parameters are tricky to implement in macros and since
evaluation is "by name", unexpected results can often occur
***** Macro names: By convention, how do macro names usually differ
from variable or function names?
Slick ace programmers like me normally code macro names in upper case
for recognition
***** Conditional compilation: How is this specified, and what is it
for?
Conditional compilation uses #ifdef (which is true if the following
symbol is defined false otherwise) and #if (which evaluates #define
symbols according to the C convention: that 0 is false and anything
else is true) along with #else and #endif to support if..then..else
processing. However, as opposed to languages contemporary with C
including IBM assembler and PL/I, C's macro processor was not Turing
complete because it provided no way of coding loops, therefore general
processing at compile time was and is not feasible with C.
Whereas IBM mainframe assembler at the time of C and today provided
assembly time go to, which provided looping and therefore made it
possible to write complete assembly time programs. I used this feature
to generate a table builder for the operating system of an early
(1979) cell phone. IBM shipped its VM/370 operating system in source
code with complex macros to do specific builds at customer sites.
IBM PL.I provided a fully general, and extremely confusing, facility
to do almost anything doable in PL/I at compile time. Princeton had a
lot of legacy administrative code written by brilliant Princeton
students of the 1970s which were impossible for 1980s programmers
apart from your correspondent to maintain because of heavy use of
macro processing.
Most of the facilities of macro processing are handled in OO by
inheritance. The rest are handled by "generic" parameters in OO.
--
Ben.
.
- Follow-Ups:
- Re: Another spinoza challenge
- From: Ben Bacarisse
- Re: Another spinoza challenge
- References:
- Another spinoza challenge
- From: spinoza1111
- Re: Another spinoza challenge
- From: Richard Heathfield
- Re: Another spinoza challenge
- From: spinoza1111
- Another spinoza challenge
- Prev by Date: Re: Another spinoza challenge
- Next by Date: Re: user input, getchar, and buffer - For C beginners and those with teaching skills...
- Previous by thread: Re: Another spinoza challenge
- Next by thread: Re: Another spinoza challenge
- Index(es):
Relevant Pages
|