Keil C51中,可以使用const来对变量进行声明修饰,但自己在认识和使用上一直存在两方面的问题:1、和另一款很流行的MCU C语言开发环境IAR中的意义有一些混淆;2、和Keil C51提供的code类型作用也有一些混淆,这里来进行一下仔细区别和笔记。
一、概述:
通过查询Keil C51 Help->uVision Help手册,搜寻const主题,在主题为"const"的一篇文章中,有详细说明了const的用法:
In ANSI C, the const type qualifier is used to define and access objects that are constant and that may not be changed. A variable that is declared with const may not be assigned to in the program. (1、Const用于修饰那些固定,不需要改变的对象;2、以Const修饰的对象不能在程序中被重新赋值)【注意:前提是在ANSI C中】
二、说明:
The Cx51 Compiler conforms to the ANSI definition of const objects.【注意:这里讨论const前提是在Cx51 编译器中,在其它编译器就不一定如此了】
1)、Variables declared with the const type qualifier alone are stored in the memory area (data, idata, xdata, and so on) associated with their definition.
(以const声明的变量存放在数据区:data,idata,xdata,而不是代码区)
2)、Variables you want to locate in ROM must be declared with the code memory type. For example:
code char test[] = "This is a text string";
(如果想将一个变量放在代码区,则必须使用code对变量进行声明)
3)、Variables declared with const far are stored in the HCONST memory area. This area is typically allocated to ROM memory.
(以const far声明的变量一般会被安排存放到代码区?,试验过,u8 const far test,编译会显示很多警告)
4)、Finally, the STRING compiler directive specifies where string constants are stored. This directive allows you to place strings in CODE memory, HCONST memory, or in XCONST memory (constant space in XDATA).
(strings对象的存放位置由STRING编译指示符来决定,默认被安排在代码区)
三、使用方法:
1)、Constant objects are typically initialized when they are defined (in your source files). The following variable definitions show different ways to create constant objects:(const对象通常在源文件中被定义时,就被初始化了特定值)
Eg.#pragma STRING(XDATA)/* table is stored in the default memory area */
const int table[2][2] ={ 0, 2, 4, 8 };/* pi is stored in the HCONST class */
const float far pi = 3.1415927;/* The string is stored in the XCONST class */
printf("This is a string\n");
上述例子描述了const对象在程序源文件中定义时,就被初始化设定了数值;
2)、When using pointers to const objects, you may exclude the const type qualifier in the pointer definition. (当使用指针指向const对象时,指针不能以const声明)
Eg.
const unsigned char mask [] ={ 0x01, 0x02, 0x04, 0x08 };const unsigned char *cp = mask;unsigned char *p = mask; /* same as cp */.
.
.*p = 'a'; // This has no effec.// It causes no error or warning*cp = 'a'; // This causes an error
As shown, it is possible to assign the address of a const object (mask) to a non-const pointer (p) and subsequently use the pointer to change the const object. In this case, the compiler does generate code to write to the const object. The effects of this code is undefined and may or may not work as expected.(通过上述例子,可以看到一种可以的用法是,使用一个非const声明的指针来指向一个const对象,然后通过指针来改变这个const对象。这种用法的效果是不定的,即可能如或不如预期所料的)【这种用法在网上也看到其他人写到,也一直知道有这种用法,但Keil Help提供的建议意思应该是尽量不用,因为这种用法生成的代码不一定能如编程者预期的方式工作】
It is not possible to use a const pointer to change the const object it points to. Attempts to do so will cause a compiler error.( 另外,不可用一个const声明的指针来指向一个const对象,这样用会导致编译器报错)
但另一种const用法是可行的:一个指针,声明指向const对象:
Eg:
char text [] = "This is a string.";
char *const textp = text;
.
.
.
*textp = 'A'; // This is OK (it changes text[0])
textp++; // This causes an error (textp is const)
textp[2] = 'B'; // This is OK (it changes text[2])
【此例在我现在看来,毫无实用价值】
归纳总结上述,即是:
1、const声明的对象被Keil C51安排在数据区(包括:data,idata,xdata etc);
2、要将变量安排到代码区,需使用code进行声明;
3、const声明的对象在源文件中定义时,即被初始化,程序中只能引用,不能复制;
4、虽然通过指针可以访问并修改const对象,但最好不要这么做,因为C51不一定会如使用者预想那样编译代码;