const定义的变量是可以被修改的,只不过不能被显式修改,报错是编译器给出的,在编译的时候,如果编译器发现const被
修改了则会报错,但是在运行的时候,却是可以修改的,因此const具有变量的属性。并不是常量。
下面这一段代码可以证明上面的判断
int main
{
char buf[4];
const int a = 0;
buf[4] = 97;
printf(“the a is %d\n”,a);
}
其中最后一句printf的目的是看下变量a的值是否改变,根据const的理解,
如果const修饰的是变量是不能被修改的话,那么a的值一定不会改变,肯定还是0。
但是在实际运行的结果中,我们发现a的值已经变为97了。
这说明const修饰的变量a,已经被我们程序修改了。
上面这个例子也很好的说明了const所修饰变量仍然是个变量,如果在函数中定义const的变量,
则const修饰的变量就会被放到栈上,如果在函数外面定义const的变量,则会被放到data区。
在一个函数中const所修饰的变量是不能被显示修改的(这个变量的作用域仍然是局部变量)。
下面的一段话是我的关于运行时全局变量和局部变量是如何在内存中分配的推测(有些内容可能不准确,仅作为自己学习时的为了后续方便理解的推测,有的部分还需要进一步验证):
首先,我们已经对程序下载到ROM的代码分布达成了共识,即分为代码区,BSS(ZI),data。(常量区
作为内存池放在了代码区,这个可以通过阅读反汇编代码看出来)。但是这只是在rom中的分布,以stm32为例,如果程序运行起来
代码是在norflash中原地执行的。而静态分配的全局变量肯定不会在norflash中赋值和读取(如果这样读写速度将很慢),一定是
要在sram中分配的,因此我推测,当程序中应用到全局变量的时候,会在内存中开辟空间,这个空间地址是编译器
在编译的时候分配的(链接地址),在rom的data或者bss段中存储的只是内存池,然后程序代码会读取内存池相应的数据复制
给sram中的内存空间,换句话说,如果在程序中没有用到某个在rom中定义的全局变量,则这个全局变量
根本就不会占用内存(但是却会占用rom空间)。
修改了则会报错,但是在运行的时候,却是可以修改的,因此const具有变量的属性。并不是常量。
下面这一段代码可以证明上面的判断
int main
{
char buf[4];
const int a = 0;
buf[4] = 97;
printf(“the a is %d\n”,a);
}
其中最后一句printf的目的是看下变量a的值是否改变,根据const的理解,
如果const修饰的是变量是不能被修改的话,那么a的值一定不会改变,肯定还是0。
但是在实际运行的结果中,我们发现a的值已经变为97了。
这说明const修饰的变量a,已经被我们程序修改了。
上面这个例子也很好的说明了const所修饰变量仍然是个变量,如果在函数中定义const的变量,
则const修饰的变量就会被放到栈上,如果在函数外面定义const的变量,则会被放到data区。
在一个函数中const所修饰的变量是不能被显示修改的(这个变量的作用域仍然是局部变量)。
下面的一段话是我的关于运行时全局变量和局部变量是如何在内存中分配的推测(有些内容可能不准确,仅作为自己学习时的为了后续方便理解的推测,有的部分还需要进一步验证):
首先,我们已经对程序下载到ROM的代码分布达成了共识,即分为代码区,BSS(ZI),data。(常量区
作为内存池放在了代码区,这个可以通过阅读反汇编代码看出来)。但是这只是在rom中的分布,以stm32为例,如果程序运行起来
代码是在norflash中原地执行的。而静态分配的全局变量肯定不会在norflash中赋值和读取(如果这样读写速度将很慢),一定是
要在sram中分配的,因此我推测,当程序中应用到全局变量的时候,会在内存中开辟空间,这个空间地址是编译器
在编译的时候分配的(链接地址),在rom的data或者bss段中存储的只是内存池,然后程序代码会读取内存池相应的数据复制
给sram中的内存空间,换句话说,如果在程序中没有用到某个在rom中定义的全局变量,则这个全局变量
根本就不会占用内存(但是却会占用rom空间)。
const不能修改指的是在其作用域内不能被修改(这不是废话嘛,在作用域外也访问不到啊)。
然而在S5PV210中,bss段,data段,和代码段都是按照链接脚本的排列顺序直接拷贝到RAM中的。链接脚本中的地址说的都是内存地址。另外bss段的清零操作是运行时候进行的,也就是如果有全局变量,则必须在start.S中将其清零。也可以将其称之为构建C语言运行环境,因为C语言标准语法中规定,未显示初始化的全局变量是0。
清零操作的汇编实现代码:
clean_bss:
ldr r0, =bss_start
ldr r1, =bss_end
cmp r0, r1 // 如果r0等于r1,说明bss段为空,直接下去
beq run_on_dram // 清除bss完之后的地址
mov r2, #0
clear_loop:
str r2, [r0], #4 // 先将r2中的值放入r0所指向的内存地址(r0中的值作为内存地址),
cmp r0, r1 // 然后r0 = r0 + 4
bne clear_loop