C语言常量与变量,c语言中常变量
《C语言深入理解系列- 常量与变量》
查看其他博文时请注意原作者。
本文为原创,欢迎转载!请注明出处:
http://blog.csdn.net/mr_raptor/article/details/7212155
常量和变量
所谓“正中有动,动中有动”,常量和变量也是如此,之前是相互依存,相互影响的。至于常数和变量,很多朋友可能觉得没什么好介绍的。它是如此简单,你可以知道它的字面意思。我想说的不是常数和变量的概念,而是它们的深层本质。
其实很多朋友在学习后面的指针的时候经常会出现问题,比如段落错误,晕指针(我称之为恐惧指针的人的症状),野指针,都是因为对常量和变量理解的不够深入,基础的理解不够实际。
常数:其值不会改变的量,称为常数。可以结合数据类型进行分类。例如:整数常量、浮点常量、字符常量等。常数可以直接引用,无需定义和初始化。
常数的分类:常数分为直接常数和符号常数。
直接常量也称为文字常量。比如12,0,4.6, a , abcd
符号常量:由宏定义:#define PI 3.14
特点:常量的值在其作用域内不会改变,并且不能再赋值。它出现时用作立即数。也就是说只能访问和读取,不能写入和赋值。
实际上,一旦声明了一个常量,该常量所在的内存空间就添加了一个只读属性,这有点类似于const关键字。
变量:其值能在其范围内变化的量称为变量。变量应该有一个名字,并在内存中占据一定的存储空间。变量必须在使用前定义。每个变量都有自己的地址。
变量的分类:变量根据其定义的类型分为不同的类型,如整型变量、字符型变量、浮点型变量、指针型变量等等。
特点:变量的值可以改变,这意味着它可以被覆盖、写入和赋值。每个变量都必须有一个名字,并绑定到它的内存空间,如图xxx所示。
图xxx可变内存空间图
代码声明了整型变量A,其类型已经决定,那么其大小为4字节(32位计算机上),那么内存中有4个连续的字节与之对应,变量A的名字代表这4个字节的空间,变量A的地址是4个连续字节开头的地址0x000。就好像酒店的每个房间都有地址一样。例如,201房间代表二楼的每个房间。叫它201不太雅观。姑且称之为牡丹厅吧。然后,我们人为地将“牡丹厅”这个名字与201室绑定。我们说牡丹厅,就知道是201室,说201室,也知道是牡丹厅。
同理,当我们说变量A时,我们知道它离地址0x000有4个字节。我们说地址0x000,就知道这是变量A的空间,所以既然A是变量,也就是说它所代表的空间里的数据是可以修改的,那么0x000地址的数据也是可以修改的。
变量名和变量值:
当变量名被声明时,它被绑定到内存中的一个地址。可以通过变量名直接找到对应的内存区域,也可以通过地址找到它的内存区域。
变量的值是存储在对应于该变量的内存区域中的二进制序列。变量的值不会因为变量的类型改变而改变。当变量被转换成相应的类型时,存储区的二进制序列被转换成该类型的形式。这也是强制类型转换能够成立的原因。
例如:
第一行代码:整型变量A以97的二进制形式存储在内存中,使用时会以十进制形式表示。
第二行代码:字符变量ch1的ASCII码是97,也存储在97的二进制中。使用时,它将被表示为字符‘a’。
第三行代码:整型变量A被强制转换为字符型。变量A中的值没有变,但它的类型变了。里面的值还是97的二进制,类型变成了char,97的二进制变成了char,就是字符‘a’。
第四行代码:声明一个字符指针变量P,P是变量,其值是变量,其值是整型变量A的值,强制将类型转换为字符指针类型。此时P中的值仍然是二进制97,但这个97的意义已经代表了一个字符指针,也就是指向一个字符的地址。
可见,变量在内存中的存储与其值无关,与其类型有关。同样,我们可以得出这样的结论:一个二进制序列对计算机本身没有任何意义,计算机也不知道这个二进制数据是干什么用的。只有针对其类型,或者出现在适当的场合,才能代表特定的意义。如果一串二进制数据出现在地址总线上,就代表一个地址;如果同样的数据出现在数据总线上,它代表一个数据。所以,当我们看到一个数据,比如:3.1415926,不能给它戴上方向性思维的帽子,认为它是圆周率,而要看清它的本质,它是一堆二进制代码。
让我们看看下面的例子:
1.
char ch= a
int a=(int)ch;
printf("%d %c\n ",a,ch);
ch是什么?箱子里有什么?什么是a?A里有什么?打印什么?
2.
int add=0x12345678
int * p=(int *)add;
add是什么?add里有什么?p是什么?P里面是什么?什么是*p?P是什么?
3.
#定义PI 3.14
int a=PI
printf("%d\n ",a);
上面的代码有问题吗?
4.
#定义PI 3.14
printf("%d\n ",PI);
代码有问题吗?
5.
#定义PI 3.14
int a=PI
PI=3.1415926
int b=PI
printf("%d %d\n ",a,b);
代码有问题吗?
6.
char * str=" hello world
printf("%s\n ",str);
*str="再见世界";
printf("%s\n ",str);
代码有问题吗?
回答:
1.测试对变量类型和类型转换的理解。Ch是字符变量,字符‘A’的二进制数在ch中,A是整数变量,字符‘A’的二进制数的整数表示在A中,表示为十进制数97。打印结果是97和a。
2.测试整数和地址类型的转换。Add是一个整数变量,add中的二进制数是0x12345678,用十进制表示。P是整数指针变量名,P中的二进制数是0x12345678,用地址0x12345678表示。*p是通过*(如果你试图打印它,会得到一个错误,因为你不一定有访问这个地址的权限)来访问地址0x12345678的数据。P是整型指针变量P的地址,因为P是变量,所以它也有自己的地址,所以它的地址可以取出来(见上面变量的定义)。
3.宏定义了一个常数PI。圆周率代表3.14。在代码执行前的预处理阶段,第二行int a=PI已经被替换为int a=3.14。将3.14赋给一个整数会丢弃小数点后的结果,只保留整数部分。打印结果是3。
4.和上面3一样,在预处理阶段用printf ("%d \ n ",3.14)替换,结果是1374389535。这是因为内存中3.14的浮点数据表示为整数。
5.第三行PI=3.1415926会导致错误。圆周率是一个常数,已被3.14=3.1415926所取代。3.14是文字常量,不能赋值。消息为“赋值无效左值出错”(常见错误信息参见C语言常见错误详细解释章节)。
6.第三行*str="再见世界"有错误。第一行把字符串常量“hello world”的首地址给了字符指针变量str,第三行用* str访问“goodbyeworld”的首地址来覆盖str指向的字符串常量“hello world”。这句话很难理解,因为有两个错误:
尝试将数据写入常量。
“hello world”是一个字符串常量,所以这个字符串空间中的内容是不能改变的。
地址应该放在指针中,所有的字符串都由第一个地址寻址。
Strcpy应该用于将字符串写入地址。*str只代表str指向的字符串中的第一个字符。肯定不能把字符串地址写成字符。
至于上面说的,目前可能还不太了解。请把C语言中的指针和数组通读一遍再详谈,一定会有不同程度的深入理解。
《C语言深入理解系列- 常量与变量》
查看其他博文时请注意原作者。
本文为原创,欢迎转载!请注明出处:
http://blog.csdn.net/mr_raptor/article/details/7212155
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。