BitArt

Ideas Worth Spreading

导航

由液晶字库的存放位置想到的

Posted on 2012-11-29 14:07  BitArt  阅读(1092)  评论(0编辑  收藏  举报

  当我们在做12864液晶的字库时,常常将一个汉字取模后,保存到一个数组中,如在zimo.h中,有:

  char zimo[]={
  /*-- 文字: 格 20--*/
  /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
  0x10,0x80,0x10,0x80,0x11,0xF8,0xFD,0x08,0x12,0x90,0x34,0x50,0x38,0x20,0x54,0xD8,
  0x57,0x06,0x91,0xF8,0x11,0x08,0x11,0x08,0x11,0x08,0x11,0x08,0x11,0xF8,0x11,0x08};

  由于该处对数组zimo[]进行了初始化,因此此处是数组的定义,而不是声明

  当几个不同的源文件分别包含这个.h文件时,编译就会出现重复定义的错误,一般的解决办法有如下两种:

方法1:规范模块化

  在我的前一篇文章《C代码与工程的规范》,已经介绍了关于模块化的文件组织,在这里,我们可以将该数组在一个.c文件中进行定义:

     /*    zimo.c     */

      char zimo[32]={
    /*-- 文字: 格 20--*/
    /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
    0x10,0x80,0x10,0x80,0x11,0xF8,0xFD,0x08,0x12,0x90,0x34,0x50,0x38,0x20,0x54,0xD8,
    0x57,0x06,0x91,0xF8,0x11,0x08,0x11,0x08,0x11,0x08,0x11,0x08,0x11,0xF8,0x11,0x08};

  然后为该.c文件配置一个.h文件,对该数组进行全局性声明,内容如下: 

/*    zimo.h     */

    extern char zimo[32];

  这样我们在使用该数组时,只需要包含zimo.h,就不会出现重复定义的错误;

方法2:利用static进行声明;

  如果MCU系统的静态存储区较大,可以使用static定义该数组,此时只使用一个.h文件即可。但是这个方法个人不推荐!

      在zimo.h中,定义数组如下: 

/*    zimo.h     */
static char zimo[32]={
    /*-- 文字: 格 20--*/
    /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
    0x10,0x80,0x10,0x80,0x11,0xF8,0xFD,0x08,0x12,0x90,0x34,0x50,0x38,0x20,0x54,0xD8,
    0x57,0x06,0x91,0xF8,0x11,0x08,0x11,0x08,0x11,0x08,0x11,0x08,0x11,0xF8,0x11,0x08};

  在.h文件中,出现static关键字意味着什么呢?

  我们知道,static关键字的作用之一是声明变量为本地变量,当A.c中,包含了zimo.h时,就相当于在A.c中定义了一个static型的数组,暂且称之为T1,它的作用范围仅限于A.c;

  同时,当B.c也包含了zimo.h时,也相当于在B.c中定义了一个static型的数组,称它为T2,它的作用范围仅限于B.c;

  两个数组T1、T2虽然重名,都叫zimo[],但是由于static的修饰,它们是互不影响的,等同于在内存空间中开辟了两块空间,分别用于保存T1和T2。这样就解决了重复定义的问题。但是弊端十分明显,就是包含了N次zimo.h,这个数组就新定义了N次,就浪费了N倍的存储空间。同时,在.h文件中出现实质性的定义,也不符合模块化编程的指导思想。

 

另附:这里附上我曾经看过的一篇文章,《在头文件中使用static意味着什么》,现将内容修改和整理如下,可以加深对static的作用的理解。

  首先,在一个头文件中,用static定义一个变量:

/*   Header.h   */
static int g_int = 3;

  其次,新建两个源文件,都包含“Header.h”:

/*   Source1.c   */
#include <stdio.h>
#include "Header.h"

void Test1() 
{
  g_int = 5;
  
  printf("g_int's address in Source1.c: %d\n", &g_int);     /*打印source1.c中g_int的地址*/
  printf("g_int's value in Source1.c: %d\n", g_int);       /*打印source1.c中g_int的值*/
}
/*   Source2.c   */
#include <stdio.h>
#include "Header.h"
void Test2()
 {
  g_int = 3;
  printf("g_int's address in Source2.c: %d\n", &g_int);    /*打印source2.c中g_int的地址*/ 
  printf(
"g_int's value in Source2.c: %d\n", g_int);     /*打印source2.c中g_int的值*/
}

然后在main函数中,调用这两个测试函数:

1 /*    Main.c   */   
2 #include "Test1.h"
3 #include "Test2.h"
4 
5 void main(void) 
6 {
7     Test1();
8     Test2();
9 }

得到的输出结果如下:

  可以看到,两个源文件中的g_int的地址和值都是不同的,说明它们即使同名,但它们是互不影响的完全不同的两个变量。这就是static本地化的作用。这种声明全局变量的做法十分的不科学,应该禁止使用。

  作为对比,下面给出正确的使用全局变量的方法:

/*    Header.h      */
extern int g_int;      /*全局变量的声明*/
/*    Header.c    */
int g_int = 0;     /*全局变量的定义*/
/*   Source1.c   */
#include <stdio.h>
#include "Header.h"
void Test1() 
{
  g_int = 5;
    printf("g_int's address in Source1.c: %d\n", &g_int);
  printf("g_int's value in Source1.c: %d\n", g_int);
}
/*   Source2.c   */
#include <stdio.h>
#include "Header.h"
void Test1() 
{
  g_int = 5;
    printf("g_int's address in Source2.c: %d\n", &g_int);
  printf("g_int's value in Source2.c: %d\n", g_int);
}
1 /*    Main.c   */   
2 #include "Test1.h"
3 #include "Test2.h"
4 
5 void main(void) 
6 {
7     Test1();
8     Test2();
9 }

运行后,得到结果如下:

可见,两个源文件使用的是同一变量。