链接功能时GCC没有错误

时间:2014-04-03 05:22:21

标签: c gcc linker

我有以下两个.c个文件

的main.c

#include <stdio.h>

int print();
int show(int);

int main()
{
    int i = 0; 
    float x = 1.0;
    int y = *((int*)(&x));

    print();

    i = show(5);
    printf("%d", i);
    printf("\n%d", y);

    return 0;
}

foo.c的

#include <stdio.h>

void print()
{
    printf("Hello World !!\n");
}

float show()
{
    return 1;
}

这是我的makefile

CC = gcc
CFLAGS = -I. -Wall -pedantic -Wconversion

.PHONY: clean

%.o: %.c
    $(CC) -c -o $@ $< $(CFLAGS) 

main: main.o foo.o
    $(CC) -o main main.o foo.o $(CFLAGS)

clean:
    rm -rf *.o
    rm -rf main

这是输出

  

Hello World !!
  1065353216个
  1065353216

如果我构建上述内容,绝对没有错误。似乎链接gcc并不关心这两个函数有不同的返回类型和不同的参数列表。

第二点是在函数show而不是从floatint进行隐式转换,位模式正在被复制,我已经使用第二个验证了printf致电。

为什么上面发生了什么?我知道由于名称损坏,g++不会发生这种情况,但这不是一个严重的问题吗?

2 个答案:

答案 0 :(得分:3)

诀窍是在头文件(foo.h)中声明您的函数,然后在源文件(foo.c)中包含该头文件。还要在任何调用foo.h中声明的函数的源文件(例如main.c)中包含头文件。

foo.h中包含foo.c允许编译器验证函数声明是否与函数定义匹配。在foo.h中包含main.c让编译器验证main.c正确使用函数,并允许编译器进行任何必要的类型转换。

通过错误地声明main.c中的函数来对编译器说谎,你发现它没有用。

<强> foo.h中

void  print( void );
float show( void );

<强>的main.c

#include <stdio.h>
#include "foo.h"

int main()
{
    int i = 0; 

    print();

    i = show();
    printf("%d\n", i);

    return 0;
}

<强> foo.c的

#include <stdio.h>
#include "foo.h"

void print( void )
{
    printf("Hello World !!\n");
}

float show( void )
{
    return 2;
}

答案 1 :(得分:1)

隐式转换不会发生,因为main的代码是使用top声明的签名生成的。答案在于拆卸。 我得到的输出也是 &#34; Hello World !! 1073741824 1065353216&#34; 这是你的diif。隐式转换发生在编译时。链接不是链接器添加隐式转换的时间。这两个文件都使用2个diff签名进行编译 它们是在自己的域中编译的,不需要任何转换。

转储函数main的汇编代码:

 0x0000000000400504 <+0>:     push   %rbp
   0x0000000000400505 <+1>:     mov    %rsp,%rbp
   0x0000000000400508 <+4>:     sub    $0x10,%rsp
   0x000000000040050c <+8>:     movl   $0x0,-0x8(%rbp)
   0x0000000000400513 <+15>:    mov    $0x3f800000,%eax
   0x0000000000400518 <+20>:    mov    %eax,-0xc(%rbp)
   0x000000000040051b <+23>:    lea    -0xc(%rbp),%rax
   0x000000000040051f <+27>:    mov    (%rax),%eax
   0x0000000000400521 <+29>:    mov    %eax,-0x4(%rbp)
   0x0000000000400524 <+32>:    mov    $0x0,%eax
   0x0000000000400529 <+37>:    callq  0x400570 <print>
   0x000000000040052e <+42>:    mov    $0x5,%edi
   0x0000000000400533 <+47>:    callq  0x400580 <show>
   0x0000000000400538 <+52>:    mov    %eax,-0x8(%rbp)
   0x000000000040053b <+55>:    mov    $0x400698,%eax
   0x0000000000400540 <+60>:    mov    -0x8(%rbp),%edx
   0x0000000000400543 <+63>:    mov    %edx,%esi
   0x0000000000400545 <+65>:    mov    %rax,%rdi
   0x0000000000400548 <+68>:    mov    $0x0,%eax
   0x000000000040054d <+73>:    callq  0x4003f0 <printf@plt>
   0x0000000000400552 <+78>:    mov    $0x40069b,%eax
   0x0000000000400557 <+83>:    mov    -0x4(%rbp),%edx
   0x000000000040055a <+86>:    mov    %edx,%esi
   0x000000000040055c <+88>:    mov    %rax,%rdi
   0x000000000040055f <+91>:    mov    $0x0,%eax
   0x0000000000400564 <+96>:    callq  0x4003f0 <printf@plt>
   0x0000000000400569 <+101>:   mov    $0x0,%eax
   0x000000000040056e <+106>:   leaveq 
   0x000000000040056f <+107>:   retq   

汇编程序转储结束。 (gdb)disass show 函数show的汇编代码转储:

   0x0000000000400580 <+0>:     push   %rbp
   0x0000000000400581 <+1>:     mov    %rsp,%rbp
   0x0000000000400584 <+4>:     mov    $0x40000000,%eax
   0x0000000000400589 <+9>:     mov    %eax,-0x4(%rbp)
   0x000000000040058c <+12>:    movss  -0x4(%rbp),%xmm0
   0x0000000000400591 <+17>:    leaveq 
   0x0000000000400592 <+18>:    retq