新网站建设运营年计划,江苏建设部网站,网站怎么做才是对搜索引擎友好,深圳外贸网站建设企业Small Device C Compiler#xff08;SDCC#xff09;是一款免费 C 编译器#xff0c;适用于 8 位微控制器。
不想看测试过程的话可以直接划到最下面看结论#xff1a;#xff09;
关于软硬件环境的信息#xff1a;
Windows 10STC89C52RCSDCC #xff08;构建HEX文件SDCC是一款免费 C 编译器适用于 8 位微控制器。
不想看测试过程的话可以直接划到最下面看结论
关于软硬件环境的信息
Windows 10STC89C52RCSDCC 构建HEX文件stcgal 1.6 向STC单片机烧录
修改代码中的数值会改变编译后的结果
显然在我们修改一些 C 语言代码的时候编译后的二进制文件也可能发生改变尤其是一些关键的数值在 51 单片机开发中C 代码会编译成 .HEX 文件然后烧录到单片机。
下面用 SDCC 编译这个示例程序来演示
这是个选择一位数码管并使其亮起的程序#include 8051.h#define decoder_in_1 P2_2 // 译码器的 3 位输入用于位选
#define decoder_in_2 P2_3
#define decoder_in_3 P2_4
#define NUMBER P0unsigned int LED_MAP[11] {0x3f, 0x6, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x7, 0x7f, 0x6f};void send_to_decoder(unsigned int position) { // position: 1 ~ 8 position--; // position: 0 ~ 7 (000 ~ 111)decoder_in_1 position 1; // low bit of position (position 001)decoder_in_2 position 2; // middle bit of position (position 010)decoder_in_3 position 4; // high bit of position (position 100)
}void main() {send_to_decoder(1); // 位选选择第 1 位数码管亮起NUMBER LED_MAP[6]; // 段选数码管显示数字 6
}改变了上面代码的位选选择第 2 位数码管亮起#include 8051.h#define decoder_in_1 P2_2 // 译码器的 3 位输入用于位选
#define decoder_in_2 P2_3
#define decoder_in_3 P2_4
#define NUMBER P0unsigned int LED_MAP[11] {0x3f, 0x6, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x7, 0x7f, 0x6f};void send_to_decoder(unsigned int position) { // position: 1 ~ 8 position--; // position: 0 ~ 7 (000 ~ 111)decoder_in_1 position 1; // low bit of position (position 001)decoder_in_2 position 2; // middle bit of position (position 010)decoder_in_3 position 4; // high bit of position (position 100)
}void main() {send_to_decoder(2); // 位选选择第 2 位数码管亮起NUMBER LED_MAP[6]; // 段选数码管显示数字 6
}对比它们生成的 HEX 文件的区别
slightwindubuntu:/xxx/diff$ diff 1.hex 2.hex
9c9:0C00BE00A42290000112009E85148022F4
---:0C00BE00A42290000212009E85148022F3可以看到第 9 行出现了区别。
头文件中没有被调用的函数
把数组 LED_MAP 放到头文件中再从主函数中调用头文件还包含了程序没有调用过的 sleep()。 swutil.h
#ifndef __SWUTIL_H__
#define __SWUTIL_H__unsigned int LED_MAP[11] {0x3f, 0x6, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x7, 0x7f, 0x6f};void sleep(unsigned int n); // sleep n (ms)#endifswutil.c
void sleep(unsigned int n){unsigned char i, j;while (n--){i 2;j 239;do{while(--j);}while(--i);}
}main.c
#include 8051.h
#include swutil.h#define decoder_in_1 P2_2 // 译码器的 3 位输入用于位选
#define decoder_in_2 P2_3
#define decoder_in_3 P2_4
#define NUMBER P0void send_to_decoder(unsigned int position) { // position: 1 ~ 8 position--; // position: 0 ~ 7 (000 ~ 111)decoder_in_1 position 1; // low bit of position (position 001)decoder_in_2 position 2; // middle bit of position (position 010)decoder_in_3 position 4; // high bit of position (position 100)
}void main() {send_to_decoder(1); // 位选选择第 1 位数码管亮起NUMBER LED_MAP[6]; // 段选数码管显示数字 6
}这时使用 SDCC 编译后生成的 HEX 文件和前面第一个实例代码生成的 HEX 文件完全一致说明没有额外的函数参与了编译也就是说尽管导入了比较复杂的头文件编译器也只会让调用过的函数参与编译。
主文件中没有调用的函数
下面这个程序在前面第一个实例代码的基础上额外定义了 sleep() 函数但是没有调用
#include 8051.h#define decoder_in_1 P2_2 // 译码器的 3 位输入用于位选
#define decoder_in_2 P2_3
#define decoder_in_3 P2_4
#define NUMBER P0unsigned int LED_MAP[11] {0x3f, 0x6, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x7, 0x7f, 0x6f};void send_to_decoder(unsigned int position) { // position: 1 ~ 8 position--; // position: 0 ~ 7 (000 ~ 111)decoder_in_1 position 1; // low bit of position (position 001)decoder_in_2 position 2; // middle bit of position (position 010)decoder_in_3 position 4; // high bit of position (position 100)
}void sleep(unsigned int n){unsigned char i, j;while (n--){i 2;j 239;do{while(--j);}while(--i);}
}void main() {send_to_decoder(1); // 位选选择第 1 位数码管亮起NUMBER LED_MAP[6]; // 段选数码管显示数字 6
}
同样是用 SDCC 编译diff 一下和第一个程序生成的 HEX 的区别可以发现文件变大了也有很多不一样的地方。
slightwindubuntu:/xxx/diff$ diff 1.hex 4.hex
6c6:030003000200C038
---:030003000200DC1C
9c9,11:0C00BE00A42290000112009E85148022F4
---:1000BE00A422AE82AF838E048F051EBEFF011FECFD:1000CE004D600A7DEF7C02DDFEDCFC80E9229000B3:0800DE000112009E851480222E
11c13:100013007900E94400601B7A009000CE780175A056
---:100013007900E94400601B7A009000EA780175A03A
17,18c19,20:0D00060075811D1200CAE58260030200032F:0400CA007582002219
---:0D00060075811D1200E6E582600302000313:0400E60075820022FD所以在 main.c 中定义的函数即使没有调用也会参与 HEX 文件的构建。
在Keil_C51编译器上的测试
另外我还将编译器换成了 Keil_C51 进行了一遍上述的测试发现不管是包含的头文件中的函数还是 main.c 中定义的函数只要没有调用都不会参与到编译中1这样有利于生成更小的 HEX 文件。
结论
在 SDCC 中使用的头文件中声明的函数没有调用的话是不会参与编译的但是在 main.c 里面直接定义的函数尽管没有调用也是会参与编译的。 以这个简单的例子看来在编译优化方面还是 Keil 做的更专业一些不过 SDCC 胜在免费是不想使用付费/破解软件时的一个不错的替代品。 这只是从上面这个简单的示例程序中表现出来的现象得到的结论编译器的实现和优化工作非常复杂在其他情况下可能表现出不同的结果。 ↩︎