Ответ 1
Здесь действительно дешевый ответ:
void
change()
{
printf("%d", 5);
exit(0);
}
: - P
Я нашел эту головоломку в бумаге C.
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
}
int main()
{
int i = 5;
change();
i = 10;
printf("%d", i);
return 0;
}
Любые решения.?
Здесь действительно дешевый ответ:
void
change()
{
printf("%d", 5);
exit(0);
}
: - P
определить?
#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;
}
Это ответ POSIX, который действительно делает то, что задает проблема:)
Он не будет работать на некоторых архитектурах/компиляторах, но он здесь.
#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: Это должно сделать его более надежным для людей с бойкотирующими заголовками.
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
}
Здесь другая возможность:
void change()
{
char const *literal = "%d";
char * ptr = (char*)literal;
ptr[0] = '5';
ptr[1] = 0;
}
Это гораздо более переносимо, чем изменение обратного адреса, но требует от вас (a) иметь компилятор, который объединяет строковые литералы (большинство из них) и (b) имеет компилятор, который не размещает константы в read- только в секции или работать на архитектуре без MMU (вряд ли в эти дни).
Кто-нибудь думал об использовании atexit?
void change (void)
{
static int i = 0;
if (i == 0) atexit (change);
if (i == 1) printf ("\r5 \b\n");
++i;
}
Обратите внимание, что в основной функции нет завершающей строки новой строки, если мы отправим 2 символа backspace в stdout, 10 будет стерто, и будет напечатано только 5.
Вызвать требуемый #include и заменить комментарий скобкой-несбалансированным текстом:
} int printf(const char *s, ...) { return fprintf(stdout,"%d",5);
Протестировано успешно. Спасибо dreamlax и Крису Лутцу за исправления.
У вас есть локальная переменная я в стеке, для которой начинается значение 5.
С change() вам нужно изменить следующую инструкцию как 5, поэтому вам нужно будет переопределить буфер в том месте, где установлено 10, и установить значение 5.
Вызов printf("%d", i);
в main()
не завершает вывод в новой строке, поведение программы определяется реализацией.
Я утверждаю, что при моей реализации программа, которая не умеет писать завершающую строку новой строки для окончательной строки, всегда печатает 5
, а затем новую строку в качестве последней строки.
Таким образом, вывод всегда будет 5, независимо от определения change()
.: -)
(Другими словами, в чем суть таких вопросов, если они не предназначены для работы на определенном оборудовании, компиляторе и т.д.?)
void change()
{
#define printf(x,y) fprintf(stdout,x,y-5)
}
Простой:
void change()
{
printf("%d\n", 5);
int foo;
close(0);
close(1);
dup2(foo, 1);
dup2(foo, 0);
}
Немного сложнее:
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);
}
}
Я подозреваю, что "правильный" ответ на это - изменить адрес возврата в стеке в функции change()
, так что когда он вернет поток управления, пропустит команду i=10
и перейдет прямо к printf
> .
Если это так, то это ужасный, уродливый вопрос и (непереносимый) ответ требуют знания архитектуры и набора инструкций.
Как насчет следующего: (только x86)
change()
{
__asm__( "mov eax, [ebp+4]\n\t"
"add eax, 4\n\t"
"mov [ebp+4], eax\n\t" );
}
Любить ответы здесь. Я получил его для работы в двух строках.
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;
}
10 никогда не достигнет выхода, потому что после того, как функция change() напечатает 5, дескриптор файла stdout будет закрыт.
Люди могут проверить, что используется следующий онлайн-компилятор C.
здесь другой:
void change()
{
#define printf(x,y) printf("5",x,y);
}
Я получаю "наименьшее #define для решения глупой проблемы"?
Я не уверен, что это всегда будет работать, но как насчет размещения переменной я в стеке следующим образом:
void change()
{
int j, *p;
for (j=-100, p=&j; j<0; j++, p++)
if (*p == 10) { *p = 5; break; }
}