深入理解计算机系统---计算符号的值

381 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情

1.假设一个C语言程序有两个源文件; main.c和proc1.c,它们的内容如下图所示。

image.png

image.png

首先理解一下什么是强符号和弱符号?

1)强符号:函数和已经初始化的全局变量

2)弱符号:未初始化的全局变量

针对强符号和弱符号,链接器会按照如下的规则去处理:

规则1:不允许强符号被定义多次。

规则2:如果一个符号在某个文件当中是强符号,在其它文件是弱符号,那么链接时将选择强符号。

规则3:如果一个符号在所有的目标文件当中都是弱符号,那么链接时将选择占用空间最大的那个。

比如,a.c当中有int a;占4个字节,b.c当中有double a;占8个字节,链接时,将选择double a;

我们也可以通过gcc的“attribute((weak))”来定义任何一个强符号为弱符号,比如:

#include<stdio.h>
#include"b.h"
int i = 10; //i是强符号
_attribute_((weak)) a= 20;//现在a是弱符号
int main()//main是强符号
{
}

1)在上述两个文件中,main.c中的强符号有x、z、main,弱符号有y: proc1.c 中的强符号有proc1,弱符号有x。其中,符号x在main.c和 proc1.c中都有定义,属于多重定义符号。

2)程序执行时,在调用proc1()函数之前,&x中存放的是x的机器数:00000101H,随后两个字节(地址为&y)存放y,它没有初始化,故通常为0;再后面两个字节存放z的机器数:0002H。如下图所示:

image.png

在调用proc1()函数以后,因为proc1()中的符号x是弱符号,因此,x的定义以main中的强符号x为准,执行x=-1.5后,便将“一1.5”的机器数BFF8000000000000H存放到了&x开始的8个字节中。即&x中为其低32位的00000000H,&y中为高32位的BFF80000H中的低 16位O000H,&z中为高32位的 BFF80000H中的高16位BFF8H。如下图所示。

image.png

因此,最终打印的结果如下:x=0,z=-16392。

3)只要将文件proc1.c中的第1行修改为“static double x;”就可以使得proc1中的x设定为本地变量,从而在proc1.o 的.data节中专门分配存放x的8个字节空间,而不会和 main中的x共用同一个存储地址。因此,也就不会破坏main中x和z的值。

字节所占的位数:

和机器字长及编译器有关系:

所以,int,long int,short int的宽度都可能随编译器而异。但有几条铁定的原则(ANSI/ISO制订的):

1 sizeof(short int)<=sizeof(int)

2 sizeof(int)<=sizeof(long int)

3 short int至少应为16位(2字节)

4 long int至少应为32位。

unsigned 是无符号的意思。

例如: 16位编译器

char :1个字节

char*(即指针变量): 2个字节

short int : 2个字节

int: 2个字节

unsigned int : 2个字节

float: 4个字节

double: 8个字节

long: 4个字节

long long: 8个字节

unsigned long: 4个字节

32位编译器

char :1个字节

char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)

short int : 2个字节

int: 4个字节

unsigned int : 4个字节

float: 4个字节

double: 8个字节

long: 4个字节

long long: 8个字节

unsigned long: 4个字节

64位编译器

char :1个字节

char*(即指针变量): 8个字节

short int : 2个字节

int: 4个字节

unsigned int : 4个字节

float: 4个字节

double: 8个字节

long: 8个字节

long long: 8个字节

unsigned long: 8个字节

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情