我有以下两个.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
而不是从float
到int
进行隐式转换,位模式正在被复制,我已经使用第二个验证了printf
致电。
为什么上面发生了什么?我知道由于名称损坏,g++
不会发生这种情况,但这不是一个严重的问题吗?
答案 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