C 难题:printf 的输出应该是“5”总是

发布于 2024-08-20 02:58:55 字数 326 浏览 6 评论 0原文

我在一篇 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;
}

有什么解决办法吗?

I found this puzzle in a C aptitude paper.

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;
}

Any solutions.?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(16

站稳脚跟 2024-08-27 02:58:55

定义?

#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;
}

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;
}
洒一地阳光 2024-08-27 02:58:55

这是一个 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;
}

编辑:这对于抵制标头的人来说应该更加强大。

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.

薆情海 2024-08-27 02:58:55
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()
{
  //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
}
命硬 2024-08-27 02:58:55

这是一个非常便宜的答案:

void
change()
{
    printf("%d", 5);
    exit(0);
}

:-P

Here's a really cheap answer:

void
change()
{
    printf("%d", 5);
    exit(0);
}

:-P

跨年 2024-08-27 02:58:55

这是另一种可能性:

void change()
{
  char const *literal = "%d";
  char * ptr = (char*)literal;
  ptr[0] = '5';
  ptr[1] = 0;
}

这比更改返回地址更可移植,但要求您(a)有一个可以池化字符串文字的编译器(大多数这样做),并且(b)有一个不会将常量放入读取中的编译器-only 部分,或者在没有 MMU 的架构上运行(现在不太可能)。

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).

她比我温柔 2024-08-27 02:58:55

有人想过使用 atexit 吗?


void change (void)
{
    static int i = 0;
    if (i == 0) atexit (change);

    if (i == 1) printf ("\r5 \b\n");
    ++i;
}

请注意,主函数中没有终止换行符,如果我们向 stdout 发送 2 个退格字符,则 10 将被删除,并且仅打印 5。

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.

染柒℉ 2024-08-27 02:58:55

调用必要的 #include,并将注释替换为括号不平衡的文本:

}
int printf(const char *s, ...) {
  return fprintf(stdout,"%d",5);

测试成功。感谢 dreamlax 和 Chris Lutz 修复了错误。

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.

如若梦似彩虹 2024-08-27 02:58:55

堆栈中有一个局部变量 i,其初始值为 5。

使用change(),您需要将下一条指令修改为5,因此您需要将缓冲区覆盖到设置为10的位置,并将其设置为5。

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.

差↓一点笑了 2024-08-27 02:58:55

main() 中的 printf("%d", i); 调用不会以换行符结束其输出,程序的行为是实现定义的。

我断言,在我的实现中,无法为最后一行编写终止换行符的程序始终会打印 5 ,后跟换行符作为最后一行。

因此,无论 change() 的定义如何,输出始终为 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.?)

千笙结 2024-08-27 02:58:55
void change()
{
#define printf(x,y) fprintf(stdout,x,y-5)
}
void change()
{
#define printf(x,y) fprintf(stdout,x,y-5)
}
树深时见影 2024-08-27 02:58:55

简单:

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);
    }
}

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);
    }
}
溺ぐ爱和你が 2024-08-27 02:58:55

我怀疑对此的“正确”答案是修改 change() 函数中堆栈上的返回地址,以便当它返回时控制流会跳过 i=10< /code> 命令并直接进入 printf

如果是这样,那么这是一个可怕的、丑陋的问题,(不可移植的)答案需要了解所使用的体系结构和指令集。

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.

怀里藏娇 2024-08-27 02:58:55

像这样的怎么样:(仅限x86)

change()  
{
    __asm__( "mov eax, [ebp+4]\n\t"
             "add eax, 4\n\t"
             "mov [ebp+4], eax\n\t" );
}

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" );
}
呢古 2024-08-27 02:58:55

喜欢这里的答案。我让它分两行工作。

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 编译器来验证这一点。

http://www.tutorialspoint.com/compile_c_online.php

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

墨洒年华 2024-08-27 02:58:55

这是一个不同的:

void change()
{
#define printf(x,y) printf("5",x,y);
}

我可以获得“解决愚蠢问题的最小#define 奖”吗?

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"?

瑾夏年华 2024-08-27 02:58:55

我不确定这是否总是有效,但是如何在堆栈上定位 i 变量,如下所示:

 void change()
 {  
     int j, *p;
     for (j=-100, p=&j; j<0; j++, p++)
        if (*p == 10) { *p = 5; break; }
 }

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; }
 }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文