c – 外部可选?

前端之家收集整理的这篇文章主要介绍了c – 外部可选?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我相信我会疯狂,但考虑以下C代码
// file1.c
int first;

void f(void)
{ first = 2; }
// file2.c
#include <stdio.h>

int first;
void f();
int main(void)
{
    first = 1;
    f();
    printf("%d",first);
}

这两个文件,由于某些原因将编译并链接在一起,并打印出来2.我始终觉得,除非我将一个或另一个(但不是两个)的定义标记为extern,否则不会编译,其实是外在的一切!

解决方法

在正常情况下(没有额外的gcc标志)你应该很好地编译这个代码
gcc file1.c file2.c

会发生什么是编译器会看到你有两个名为同一个东西的全局变量,也没有被初始化.然后,它将将未初始化的全局变量放在代码**的“常用”部分中.换句话说,它将只有一个“第一个”变量的副本.这是因为gcc的默认值为-fcommon

如果要使用-fno-common标志进行编译,则会收到您正在考虑的错误

/tmp/ccZNeN8c.o:(.bss+0x0): multiple definition of `first'
/tmp/cc09s2r7.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status

解决这个问题,你可以将extern添加到除变量之外的所有变量中.

警告:
现在假设你有两个不同大小的全局未初始化的数组:

// file1.c
int first[10];

// file2.c
int first[20];

好的猜测,用gcc -Wall file1.c file2.c编译它们不会产生任何警告或者错误,即使它的大小不同,这个变量是很常见的!

//objdump from file1.c:
 0000000000000028       O *COM* 0000000000000020 first

 //objdump from file2.c:
 0000000000000050       O *COM* 0000000000000020 first

这是全球变量的危险之一.

**如果您查看* .o文件的objdump(您必须使用gcc -c编译才能生成它们),您将首先看到放在通用(* COM *)部分中:

mike@mike-VirtualBox:~/C$objdump -t file2.o

a.o:     file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 file2.c
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 l    d  .bss   0000000000000000 .bss
0000000000000000 l    d  .rodata    0000000000000000 .rodata
0000000000000000 l    d  .note.GNU-stack    0000000000000000 .note.GNU-stack
0000000000000000 l    d  .eh_frame  0000000000000000 .eh_frame
0000000000000000 l    d  .comment   0000000000000000 .comment
0000000000000004       O *COM*  0000000000000004 first
0000000000000000 g     F .text  0000000000000039 main
0000000000000000         *UND*  0000000000000000 f
0000000000000000         *UND*  0000000000000000 printf
原文链接:https://www.f2er.com/c/111829.html

猜你在找的C&C++相关文章