原创 今天从公司离职了。

2009-11-2 17:57 2768 7 7 分类: 工程师职场
div class="tit">ICC中const的使用
 



现象1:*****************************************************************************************************************


在使用指针作为函数的参数时,指针指向的内容如果是 被const修修饰过的一维数组,编译时会出错。


例如定义:const unsigned char AVR_bmp[]={……};


函数中这样调用:void LCD_draw_bmp_pixel(unsigned char X,unsigned char Y,unsigned char *map,unsigned char Pix_x,unsigned char Pix_y)
{……;LCD_write_byte(map[i+n*Pix_x], 1);}



现象2:*****************************************************************************************************************


在使用指针作为函数的参数时,指针指向的内容如果是 被const修修饰过的二维数组,编译时会出错。


例如定义:const unsigned char HZK[][32]={……};


函数中这样调用:void LCD_write_chinese_string(unsigned char X, unsigned char Y,unsigned char ch_with,unsigned char num,unsigned char *addrs,unsigned char line,unsigned char row)
{……;LCD_write_byte(addrs[line+i][n],1);}



原因:****************************************************************************************************************


ICCAVR里关于const用法的说明:


const int table[] = { 1, 2, 3 };
const char *ptr1;
char * const ptr2;
const char * const ptr3;


"table" is a table allocated in the program memory. "ptr1" is an item in the data memory that points to data in the program memory. "ptr2" is an item in the program memory that points to data in the data memory. Finally, "ptr3" is an item in the program memory that points to data in the program memory. In most cases, items such as "table" and "ptr1" are probably the most typical. The C compiler generates the LPM instruction to access the program memory.
Note that the C Standard does not require "const" data to be put in the read-only memory, and in a conventional architecture, this would not matter except for access rights. So, this use of the const qualifier is unconventional, but within the allowable parameters of the C standard. However, this does introduce conflicts with some of the standard C function definitions.


双龙的翻译:


非标准C 解决了这个问题ImageCraft AVR 编译器使用"const"限定词表示项目是在程序存贮器中注意对指针描述这个const 限定词可以应用于不同的场合不管是限定指针变量自己还是指向项目的指针。


例如
const int table[] = { 1, 2, 3 };
const char *ptr1;
char * const ptr2;
const char * const ptr3;


"table"是表格式样分配进程序存贮器
"ptr1"是一个项目在数据存贮器而指向数据的指针在程序存贮器
"ptr2"是一个项目在程序存贮器而指向数据的指针在数据存贮器
最后"ptr3"是项目在程序存贮器而指向数据的指针也在程序存贮器


在大多数的例子中"table" 和和"ptr1"是很典型的C编译器生成LPM 指令来访问程序存贮器


注意C 标准不要求"const"数据是放入只读存贮器中而且在传统结构中除了正确访问就没有要紧的了因而在承认参数的C 标准中使用const 限定是非传统的无论如何这样做与标准C函数定义是有一定冲突的


例如标准"strcpy"的原型是strcpy(char *dst, const char *src) 带有const 限定的第二个参数表示函数不能修改参数然而在ICCAVR 下const 限定词表示第二个参数指向程序存贮器是不合适的因此这些函数定义设有const 限制


最后注意只有常数变量以文件存贮类型放入FLASH 中例如定义在函数体外的变量或有静态存贮类型限制的变量如果你使用有const 限制的局部变量将不被放入FLASH 中而可能导致不明确有结果



分析*******************************************************************************************************


出错是因为违背了两个原则:


1,如果按照平时定义:char *ptr则指针指向放在数据存储器里的数组,如果该指针引用放在程序存储器的const数组则出错.


2,const 限定词表示第二个参数指向程序存贮器是不合适的


那么现象1可以这么改:


定义:const unsigned char AVR_bmp[]={……};


函数中这样调用:void LCD_draw_bmp_pixel(const unsigned char *map,unsigned char X,unsigned char Y,unsigned char Pix_x,unsigned char Pix_y)
{……;LCD_write_byte(map[i+n*Pix_x], 1);}


!!用const修饰指针,被修饰的指针必须作为函数的第一个参数被定义!!


现象2如果这样改:


定义:const unsigned char HZK[][32]={……};


调用:void LCD_write_chinese_string(const unsigned char *addrs,unsigned char X, unsigned char Y,unsigned char ch_with,unsigned char num,unsigned char line,unsigned char row){……;LCD_write_byte(addrs[line+i][n],1);}


却依然不能通过编译,因为可以把数组理解为双重的指针(示意图如下),上面这样定义只是把 指向第二维数组数据 的 指针 指向了code区,指向指针的指针却没有正确指向,但是又不能这样定义:const const unsigned char *addr;


               ->HZK[0][0]
       HZK[0] ->HZK[0][1]
               ->HZK[0][2]
                   .
                   .
                   .
HZK->
               ->HZK[1][0]
       HZK[1] ->HZK[1][1]
               ->HZK[1][2]
                   .
                   .
                   .
    
       .
       .
       .


因此被const修饰了的二维数组只能这样了:


定义:const unsigned char HZK[][32]={……};


调用方法:void LCD_write_chinese_string(const unsigned char *addrs,unsigned char X, unsigned char Y,unsigned char ch_with,unsigned char line,unsigned char row){…LCD_write_byte(addrs[n],1);…};//此时*addrs只是指向一维的


使用处:LCD_write_chinese_string(HZK[0],13,2,16,0,0);//此处就是把HZK[0]当作 指向HZK[][32]数组 的第二维 的指针 来用,这样就能不改变数组定义方式。

文章评论0条评论)

登录后参与讨论
我要评论
0
7
关闭 站长推荐上一条 /2 下一条