Solved

Another C Programming Puzzle

Posted on 2004-08-13
20
1,310 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
  • 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
 
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
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 

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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

HOW TO: Connect to the VMware vSphere Hypervisor 6.5 (ESXi 6.5) using the vSphere (HTML5 Web) Host Client 6.5, and perform a simple configuration task of adding a new VMFS 6 datastore.
A Short Story about the Best File Recovery Software – Acronis True Image 2017
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

708 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

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now