Solved

Another C Programming Puzzle

Posted on 2004-08-13
20
1,329 Views
Last Modified: 2007-12-19
void fun(void)
{
/*Do something here so that the main function prints something other than 20 */
}


void main()
{
             int i = 20;
             fun();
             printf("%d", i);
}

Question: What should be the contents of function fun() so that the printf in main prints something other than 20?
0
Comment
Question by:lemmeC
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 6
  • 3
  • +1
20 Comments
 
LVL 12

Expert Comment

by:andrewjb
ID: 11791120
Fiddle with the stack to change the 20 to something else. Is asm {} allowed? Not very portable..
0
 
LVL 5

Author Comment

by:lemmeC
ID: 11791134

>> Is asm {} allowed?
No clue. In fact, I do not know the solution.
For the moment, everything is allowed. :-)
 
0
 
LVL 12

Expert Comment

by:andrewjb
ID: 11791147
Platform specified?
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 5

Author Comment

by:lemmeC
ID: 11791162
Nope, nothing other than the question is specified.

I use Windows 2K on a Pentium with VC++ 6.0 and Turbo-C 2.01. Can also access a HP-UX on a Pentium with gcc on it.
I am looking for a solution which works on atleast one of these compilers.
0
 
LVL 12

Expert Comment

by:andrewjb
ID: 11791167
void fun(void)
{
  int x[1];
  x[3] = 20;
}

works on my compiler. If it doesn't on yours, try changing the x[3] to x[2] or x[4] or something.

.. and you'll probably need optimisations off.

0
 
LVL 5

Author Comment

by:lemmeC
ID: 11791225
Turbo C crashes with that code. Will try it out on VC and gcc.
0
 
LVL 12

Accepted Solution

by:
andrewjb earned 250 total points
ID: 11791251
Actually, you could probably try something like..

void fun(void)
{
  int x[1];

  int i;

  for ( i = -10 ; i < 10 ; i++ )
    if ( x[i] == 10 ) x[i] = 20;
}
0
 
LVL 5

Author Comment

by:lemmeC
ID: 11791671
Great. With some modifications, it worked on all 3 compilers (VC, Turbo C, gcc). Thanks!

Modified program:

void fun(void)
{
  int x[1];

  int i;

  for ( i = -50 ; i < 50 ; i++ )
    if ( x[i] == 20 ) x[i] = 10;  
}
0
 
LVL 12

Expert Comment

by:andrewjb
ID: 11791710
Ooops. Sorry. int i=20. I copied that to int i=10 which is why my last one was wrong :-)

Anyway, this isn't guaranteed to work at all. It's naughty, unportable and bad code.

Hope this is a puzzle, and not a real-world programming question!

0
 
LVL 5

Author Comment

by:lemmeC
ID: 11791804
Its just a puzzle, alright. Asked by my colleague as a challenge.
Anyways, thanks.
0
 

Expert Comment

by:olsworld
ID: 11795091
good puzzle and amazing solution. i still wonder how the fun() is changing value of a variable declared in main ()... can any one of you pls throw some light on how it happens???

thanx a ton
0
 
LVL 5

Author Comment

by:lemmeC
ID: 11807024
olsworld,

>>can any one of you pls throw some light on how it happens?

The local variables of each function (including main) are kept in the function's activation record. The activation records reside in stack memory. In this case, the record for fun() would be adjacent to the record for main(). Andrew's solution searches for the variable i of main in the stack memory adjacent to the array variable x of fun and replaces i's contents with a new value.
Just goes to show how risky it is to use arrays without bounds checking.
0
 

Expert Comment

by:olsworld
ID: 11815578
i still wonder why it is not throwing memory leak error as it access the memory allocated to the program. and what if some other memory area also contains same value assigned to the variable declared in main().

is this solution guranteed to work on all platforms and all times? i doubt.
0
 
LVL 5

Author Comment

by:lemmeC
ID: 11817625
>> is this solution guranteed to work on all platforms and all times?
No, it isn't. As Andrew pointed out, its unportable and dangerous code, and should never be used in serious programs.
0
 

Expert Comment

by:olsworld
ID: 11843058
thanx a lot lemmeC for clearing my doubts.
0
 

Expert Comment

by:krkiran
ID: 11879671
Hi,

One possible solution is,

void fun(void)
{
  int j;
  *( (int*)((int*)(*(&j+1))-1) )=25;

  /*Explanation for the above statement
    (&j+1) - gives the EBP(Base Pointer) of fun()
    ( *(&j+1) ) - gives the EBP of main which is stored in fun() stack frame.
    ( (int*)(*(&j+1)) -1 ) - converting it into integer pointer and then decrementing it, to get the actual address of 'i' in main()'s stack frame
    *( (int*) ((int*)(*(&j+1))-1)  ) - Again converting it into integer pointer and changing the actual value of 'i' .
  */

}


void main()
{
           int i = 20;
           fun();
           printf("%d", i);
}

You can better use this code which tries to calculate the address of i in fun() and then changes its value. It is working with Linux, but not with Solaris. The stack frame generated by solaris might be different. lemmC, do you know how  stack frame is generated in solaris?

Thanks
Ravikiran
0
 
LVL 5

Author Comment

by:lemmeC
ID: 11879905
Ravikiran,
       Your code seems good, and your explanation is convincing. But it dumped core on HP-UX. I do not have a Linux system around right now. Will try it out when I get hold of one.

For the Solaris stack frame format, take a look at http://segfault.net/~scut/cpu/sparc/sparcstack/sparcstack.html.

0
 
LVL 5

Author Comment

by:lemmeC
ID: 11989394
Found a neat (and platform independent) way of doing it.

void fun(void)
{
#define printf(a,b) printf("10");
}

void main()
{
           int i = 20;
           fun();
           printf("%d", i);
}
0
 
LVL 12

Expert Comment

by:andrewjb
ID: 11989414
Excellent. Give the points (back) to that man!
0
 
LVL 5

Author Comment

by:lemmeC
ID: 11989421
No need. Your answer was great too! And I can't accept my own answer as a solution. :-)
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
What's This Thing? 4 398
Need help understanding this code 15 792
Find the lowest value that causes an equation to be greater than zero? 3 319
bucky balls 5 x 5 - things to make 2 552
Arrow Electronics was searching for a KVM  (Keyboard/Video/Mouse) switch that could display on one single monitor the current status of all units being tested on the rack.
Although a lot of people devote their energy toward marketing for specific industries, there are some basic principles that can be applied to any sector imaginable. We’ll look at four steps to take and examine how those steps were put into action fo…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…
Attackers love to prey on accounts that have privileges. Reducing privileged accounts and protecting privileged accounts therefore is paramount. Users, groups, and service accounts need to be protected to help protect the entire Active Directory …

749 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question