[comp.lang.c] Explanation, someone??

burzin@skat.usc.edu (Burzin N. Engineer) (06/15/91)

Hi,
	I just gave an interview which had a C quiz and there was this program
that really confused me. I have compiled the program and can still not figure
out what is going on. Any reference or help will be appreciated.
---
char *c[] = {
  "ENTER",
  "NEW",
  "POINT",
  "FIRST"
  };
char **cp[] = { c+3, c+2, c+1, c};
char ***cpp = cp;
main()
{
  printf("%s", *++cpp);
  printf("%s", *--*++cpp+3);
  printf("%s", *cpp[-2]+3);
  printf("%s\n", cpp[-1][-1]+1 );
}

When run it produces:
ERSTEW
=========================================
Another one is :
char input[] = "SSSWILTECH1\1\11W\1WALLMP1";
main()
{
  int i, c ;

for (i=2; (c=input[i]) != '\0'; i++){
  switch(c) {
  case 'a': putchar('i'); continue;
  case '1': break;
  case 1: while((c = input[++i]) != '\1' && c!='0' );
  case 9: putchar('S');
  case 'E':
  case 'L': continue;
  default: putchar(c);
           continue;
  }
  putchar(' ');
}
putchar('\n');
}

which produces:
SWITCH SWAMP

...and to think I thought I knew C.
I would sincerely appreciate some explanation. Thank You.
-- 
===============================================================================
Burzin N. Engineer	Tel. No.Offc: (213) 740 2827 | Home (213) 640 8566
University Computing Services			ARPA: burzin@usc.edu
University of Southern California		UUCP: ..uunet!usc!burzin

wirzeniu@klaava.Helsinki.FI (Lars Wirzenius) (06/15/91)

[ I have edited the code for brevity. --liw ]
>char *c[] = { "ENTER", "NEW", "POINT", "FIRST" };
>char **cp[] = { c+3, c+2, c+1, c};
>char ***cpp = cp;
>main() {
>  printf("%s", *++cpp);
                ^- are you certain there isn't a * missing here? The
type of *++cpp is char**, which is not what printf expects, but if you
insert the asterisk, you get **++cpp with the type char* and the output
is POINTERSTEW.

>  printf("%s", *--*++cpp+3);
>  printf("%s", *cpp[-2]+3);
>  printf("%s\n", cpp[-1][-1]+1 );
>}

I didn't see anything wrong with the other program, "SWITCH SWAMP \n" is
the expected output (note the space before the newline). One way to
understand it is to go through it with a pen and some paper and keep
trace of each variable at every step.
-- 
Lars Wirzenius     wirzeniu@cc.helsinki.fi

ttobler@unislc.uucp (Trent Tobler) (06/22/91)

From article <33641@usc.edu>, by burzin@skat.usc.edu (Burzin N. Engineer):
> Hi,
> 	I just gave an interview which had a C quiz and there was this program
> that really confused me. I have compiled the program and can still not figure
> out what is going on. Any reference or help will be appreciated.
> ---
> char *c[] = {
>   "ENTER",
>   "NEW",
>   "POINT",
>   "FIRST"
>   };
> char **cp[] = { c+3, c+2, c+1, c};

translation to something humans can grasp (not really valid C code):

cp[] = { &"FIRST", &"POINT", &"NEW", &"ENTER" };

> char ***cpp = cp;
> main()
> {
>   printf("%s", *++cpp);

This statement may cause problems, because *++cpp is not a (char *),
it is a (char **), so whatever the address of "POINT" is gets interpreted
as a array of characters.  Depends on the compiler/machine what happens.
Anyway, if the machine doesn't trap it, it does have the effect of setting
cpp to &cp[1].

>   printf("%s", *--*++cpp+3);

  cpp now points to &cp[2].  cp[2] gets decremented (set to c+0, or &"ENTER"),
  which we dereference to "ENTER", and then add 3 to get "ER", which is
  printed.

>   printf("%s", *cpp[-2]+3);

  cpp[-2] is cp[0], equal to &"FIRST", which is dereferenced to give "FIRST",
  we add 3 and get "ST", which is printed.

>   printf("%s\n", cpp[-1][-1]+1 );

  cpp[-1] is cp[1], equal to c + 2 (&"POINT"), which we dereference after
  subtracting one giveing c[1], or "NEW".  Add one to get "EW", and print
  it, followed by a line-feed.

> }
> 
> When run it produces:
> ERSTEW

Yes, that is the result, if we ignore what happens in the first printf
statement.


> =========================================
> Another one is :
> char input[] = "SSSWILTECH1\1\11W\1WALLMP1";
> main()
> {
>   int i, c ;
> 
> for (i=2; (c=input[i]) != '\0'; i++){
>   switch(c) {
>   case 'a': putchar('i'); continue;
>   case '1': break;
>   case 1: while((c = input[++i]) != '\1' && c!='0' );
>   case 9: putchar('S');
>   case 'E':
>   case 'L': continue;
>   default: putchar(c);
>            continue;
>   }
>   putchar(' ');
> }
> putchar('\n');
> }

Because this has a loop, I will roll it out, and show only the important
parts:
__i__  __c__   __switch_action__
  2     'S'     prints an 'S', restarts loop
  3     'W'     prints a 'W', restarts loop
  4     'I'     prints an 'I', restarts loop
  5     'L'     restarts loop
  6     'T'     prints a 'T', restarts loop
  7     'E'     restarts loop
  8     'C'     prints a 'C', restarts loop
  9     'H'     prints an 'H', restarts loop
  10    '1'     breaks out of case, and prints a ' '.
  11    1       begin a while loop
        9          i gets incremented; test succeeds.
        'W'        i gets incremented; test succeeds
        1          i gets incremented; test fails
                prints an 'S'. restarts loop.
  15    'W'     prints a 'W', restarts loop.
  16    'A'     print an 'A', restart loop.
  17    'L'     restart loop
  18    'L'     restart loop
  19    'M'     prints an 'M', restarts loop.
  20    'P'     prints a 'P', restarts loop.
  21    '1'     breaks out of case, and prints a ' '.
  22    0
 at this point, the for loop test fails, and we drop out of the loop, print
 a line feed, and exit.

> 
> which produces:
> SWITCH SWAMP

Yep, that's what I got too.

> 
> ...and to think I thought I knew C.
> I would sincerely appreciate some explanation. Thank You.

Yes, these are quite obscure.  I would wonder why they gave such a test.
Even very experience programmers could get caught up in the complexity and
flounder around.  Also, were you told that the first one will print
what it did, because it is very dependant on the compiler and machine, and
could very possibly cause an illegal reference.

--
  Trent Tobler - ttobler@csulx.weber.edu

fredch@quad4.UUCP (Fred Christiansen) (06/27/91)

>From article <33641@usc.edu>, by burzin@skat.usc.edu (Burzin N. Engineer):
>> Hi,
>> 	I just gave an interview which had a C quiz ..

Sounds like you interviewed at Microsoft (what they gave me was a tad diff).

>> char *c[] = {"ENTER", "NEW", "POINT", "FIRST"};
>> char **cp[] = { c+3, c+2, c+1, c};
>> [Then, a bunch of cryptic ptr stuff]

>> Another one is :
>> char input[] = "SSSWILTECH1\1\11W\1WALLMP1";
>> [Switch inside a loop]

When I taught at Portland State U a couple years back, these were precisely
two of the questions on the final prepared by the previous adjunct prof.
I felt that spending the time to run them thru such a beast as the first
was probably ill spent as it was not "real life", IMHO.  While the second
is equally non "real life", it is simpler to understand...so I stole it 8-)
and used variations on the theme on the finals I gave.  Hmm, wonder where
the original is from?  The Obfuscated C Contest?
--
Fred Christiansen     |  Email:  fredch@phx.mcd.mot.com
Motorola TSD (DW278)  |     or:  uunet!phx.mcd.mot.com!fredch
2900 S. Diablo Way    |  Voice:  602-438-3464
Tempe, AZ  85282      |    Fax:  602-438-3836
  Contentment:  Knowing that the more I release earthly possessions, the more
    I can grasp eternal treasures (cf.  II Corinthians 4:18).