I found this puzzle in a C aptitude paper.
void change()
{
//write something in this function so that output of printf in main 开发者_如何学Cfunction
//should always give 5.you can't change the main function
}
int main()
{
int i = 5;
change();
i = 10;
printf("%d", i);
return 0;
}
Any solutions.?
define?
#include <stdio.h>
void change()
{
//write something in this function so that output of printf in main function
//should always give 5.you can't change the main function
#define printf_ printf
#define printf(a, b) printf_("5");
}
int main()
{
int i = 5;
change();
i = 10;
printf("%d", i);
return 0;
}
This is a POSIX answer that really does what the problem asks :)
It won't work on some architectures/compilers but it does here.
#include <stdio.h>
void
change () {
void _change();
_change();
}
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/mman.h>
void
_change()
{
int main();
uintptr_t m=(uintptr_t)main;
uintptr_t ps=sysconf(_SC_PAGESIZE);
m/=ps;
m*=ps;
mprotect((void*)m,ps,PROT_READ|PROT_WRITE|PROT_EXEC);
char *s=(char*)(intptr_t)main;
s=memchr(s,10,ps);
*s=5;
mprotect((void*)m,ps,PROT_READ|PROT_EXEC);
}
int
main() {
int i=5;
change();
i=10;
printf ("%d\n",i);
return 0;
}
EDIT: This should make it more robust for people with boycotting headers.
void change()
{
//write something in this function so that output of printf in main function
//should always give 5.you can't change the main function
#define i a=5,b
}
Here's a really cheap answer:
void
change()
{
printf("%d", 5);
exit(0);
}
:-P
Here's another possibility:
void change()
{
char const *literal = "%d";
char * ptr = (char*)literal;
ptr[0] = '5';
ptr[1] = 0;
}
This is much more portable than changing the return address, but requires you to (a) have a compiler that pools string literals (most do), and (b) have a compiler that doesn't place constants in a read-only section, or be running on an architecture with no MMU (unlikely these days).
Anybody thought of using atexit?
void change (void)
{
static int i = 0;
if (i == 0) atexit (change);
if (i == 1) printf ("\r5 \b\n");
++i;
}
Note that there is no terminating newline in the main function, if we send 2 backspace characters to stdout, the 10 will be erased, and only the 5 will be printed.
Invoke the requisite #include, and replace the comment with the parenthesis-unbalanced text:
} int printf(const char *s, ...) { return fprintf(stdout,"%d",5);
Tested successfully. Thanks to dreamlax and Chris Lutz for bugfixes.
You have a local variable i in the stack that has a value of 5 to begin with.
With change(), you need to modify the next instruction to be 5 so you would need to buffer override to that location where 10 is set, and have it set to 5.
The printf("%d", i);
call in main()
doesn't end its output in a newline, the behavior of the program is implementation-defined.
I assert that on my implementation, a program that fails to write a terminating newline for the final line always prints 5
followed by a newline as its last line.
Thus, the output will always be 5, whatever the definition of change()
. :-)
(In other words, what's the point of such questions, unless they're meant to run on particular hardware, compiler, etc.?)
void change()
{
#define printf(x,y) fprintf(stdout,x,y-5)
}
Simple:
void change()
{
printf("%d\n", 5);
int foo;
close(0);
close(1);
dup2(foo, 1);
dup2(foo, 0);
}
Slightly more sophisticated:
void change()
{
int *outfd = malloc(2 * sizeof(int));
char buf[3];
pipe(outfd);
if(!fork())
{
read(outfd[0], buf, 2);
if(buf[0] == '1' && buf[1] == '0')
{
printf("5\n");
}
else
{
write(1, buf, 2);
}
while(1);
}
else
{
close(1);
dup2(outfd[1], 1);
}
}
I suspect that the "correct" answer to this is to modify the return address on the stack within the change()
function, so that when it returns the control flow skips the i=10
command and goes straight to the printf
.
If so then that is a horrible, ugly question and the (non-portable) answer requires knowledge of the architecture and instruction set used.
How about something like this: (x86 only)
change()
{
__asm__( "mov eax, [ebp+4]\n\t"
"add eax, 4\n\t"
"mov [ebp+4], eax\n\t" );
}
Loving the answers in here. I got it to work in two lines.
void change()
{
//write something in this function so that output of printf in main function
//should always give 5.you can't change the main function
/* print a 5 */
printf("5\n");
/* Close standard output file descriptor */
close(1);
}
int main()
{
int i = 5;
change();
i = 10;
printf("%d", i);
return 0;
}
The 10 will never reach the output because after the change() function prints a 5, the stdout file descriptor is closed.
People can verify that using the following online C compiler.
http://www.tutorialspoint.com/compile_c_online.php
here is a different one:
void change()
{
#define printf(x,y) printf("5",x,y);
}
do I get the "smallest #define to solve a silly problem award"?
I am not sure this would always work, but what about locating the i variable on the stack like this:
void change()
{
int j, *p;
for (j=-100, p=&j; j<0; j++, p++)
if (*p == 10) { *p = 5; break; }
}
精彩评论