【问题标题】:Is it garbage value that is being printed?是正在打印的垃圾值吗?
【发布时间】:2016-05-02 08:45:52
【问题描述】:
    #include <stdio.h>
    #include <conio.h>
    int f(int a){
        int i,f=1;
        for(i=1; i<a; i++)
            f=f*i;
        return f;
    }
    void main(){
        int k;
        clrscr();
        int (*u)(int);
        u=&f;
        printf("%d", u);
        getch();
    }

上面的代码在TurboC++上打印657,输出不随时间变化,那不是垃圾值吗?

    #include <stdio.h>
    int f(int a){
        int i,f=1;
        for(i=1; i<a; i++)
        f=f*i;
        return f;
    }
    int main(){
        int k;
        int (*u)(int);
        u=&f;
        printf("%d", u);
        return 0;
    }

而这个修改版的代码,返回:

    4199220 on CodeBlocks
    4199728 on DevC++
    134521824 on OnlineIDE
    134513824 on gcc 4.9.2

而且这些值似乎不会随着不同的运行而改变。 输出当然取决于编译器,但 请解释一下这个输出是如何产生的?

【问题讨论】:

  • 未定义行为会做未定义和变化的事情。 11 点有更多新闻。
  • 你正在打印函数 f 的地址。它不必是任何特定的值。
  • 另外,正确的格式说明符应该是 %p (void*void(*)() 之间也可能存在一些问题)
  • NAA 但使用int main(void) 而不是void main()
  • 每天都有人想要定义未定义的行为:(如果你想确切地知道你的系统上发生了什么,那么你自己单步执行汇编指令就会发现。不要打扰但是,发布您的结果,因为它们仅适用于您的系统,对其他人无用。

标签: c pointers output function-pointers


【解决方案1】:

附言

printf("%d", u);

您将 指针 u 打印为十进制数,即您打印 u 的值,它指向的内容。

此地址可能不同,因为不同的编译器和链接器可能会将其放置在不同的位置,没有“标准”放置函数的位置。

此外,由于您使用格式"%d" 来打印指针,因此该行为在技术上是未定义。要打印指针,您应该使用"%p" 格式,并将指针转换为void *(有关更多信息,请参见例如this printf (and family) reference)。

【讨论】:

  • 我认为他更感兴趣的是为什么他会得到特定的输出而不是 printf 的工作原理。
  • 将函数指针转换为对象指针void* 也是未定义的。您最好转换为无符号整数,因为这至少是实现定义的。
【解决方案2】:
printf("%d", u);

在上面的行中,u 是一个指向函数的指针。当您将此地址解释为 int 并打印时,行为未定义。

【讨论】:

  • 但是为什么那个地址总是一样呢?
  • 未定义意味着它可能相同、零、不同、崩溃或可能打印您的名字。为了不迂腐,您的文件可能每次都以相同的方式加载到内存中。
  • 但这并没有发生,我在不同的笔记本电脑上尝试并一次又一次地做,但答案总是 657 在 turbo C++ 上,这怎么能称为未定义?
  • @Aniq55 我猜(由于 conio.h)第一个是 MS-DOS 编译并启动的。其他人则在虚拟化内存管理平台上。
  • 我理解其中的区别,但我唯一的问题是,如果它未定义和随机,为什么总是将相同的内存位置分配给函数???