计算机内存可以记录大量的信息,只有记录在内存中的信息才是可以使用的。计算机的内存管理者是操作系统。程序可以根据需要向操作系统申请存储区,所有存储区必须先申请并经过操作系统分配后才能由程序使用。我们知道计算机里的信息可以简单划分为:
/指令
/控制信息
信息 - \控制字
\数据信息
|
/ \
数值信息 非数值信息
/ \ / \
定点数 浮点数 字符数据 逻辑数据
C语言中,可以用变量来代表内存中的一个存储区,并可以通过变量名来区分不同存储区。源程序中可以通过变量声明(定义)语句可以向操作系统申请存储区。变量名可以代表两个不同的东西,一是代表存储区本身,二是代表存储区里面存放的数据。
C语言变量分多种类型(数据类型),不同类型变量的数据信息在存储区是有区别的,不同类型的变量可以参与的操作也是有区别的。
计算机中的内存基本存储单元是字节byte,最小存储单元是位bit,8bit组成一个字节。每个字节可以用来表示256个数字。我们之所以对计算机中的数据进行分组,划分数据类型就是因为不同数据占有存储空间不一。
字符类型一般占内存一个字节,因此可以通过数字表示256个不同的字符,256个字符各自对应着一个数字,这数字或者介于-127~127或者介于
0-255之间,具体字符所对应的数字取决于编译器。但是一般对于0~127这部分数值和字符的对应关系都是固定的,都是有共识的,这就是ASCII码
表。ASCII码表规定了128个字符对应的数字。所以我们说ASCII码表规定了字符到数字之间的对应关系,ASCII码从0~127.这部分对应没有
编译器差异。
在C语言中使用char表示字符类型,该类型的字符和数字的对应关系取决于编译器,但是对于0~127这部分数字对应的字符是符合ASCII码规定的。
在C语言中还有unsigned char,叫做无符号字符类型。该类型字符和数字对应关系式固定的,没有编译器差异。当然对于0~127这部分数字对应的字符依然是符合ASCII码规定的。
short叫做短整型类型,一般占有2byte,可以表示65535个数字。
unsigned short叫做无符号短整型,一般占有2byte,可以表示65535个数字,而且全部是无符号数,全是正数,数值范围是[0,65534]
long叫做长整型,一般占有4byte
unsigned long叫做无符号长整型,一般占有4byte
int叫做整型,一般占有4byte
unsigned int叫做无符号整型,一般占有4byte
float叫做单精度浮点数类型,一般占有4byte
double叫做双精度浮点数类型,一般占有8byte
long double叫做高精度浮点类型,一般占有12byte
--->以上说的是一般情况,实际应该视计算机平台而定,例如我的计算机lotus-Laptop用sizeof操作符查看结果如下:
##################################################
int->4
unsigned int->4
unsigned->4
short int->2
short->2
unsigned short int->2
unsigned short->2
long int->4
long->4
unsigned long int->4
unsigned long->4
char->1
unsigned char->1
float->4
double->8
long double->12
##################################################
数值信息分定点数和浮点数。其中定点数也称为整型数,浮点数也称为实型数。
数值信息在机器中的表示:
数值信息在机器内的表达形式称为"机器数",而"机器数"代表的数值称为此"机器数"的真值。("机器数"采用的二进制编码方法是补码表示方法。)
数值信息在计算机内采用符号数字化处理后,计算机就可以识别和表示数值信息了,为了改进带符号数值的运算方法,人们提出了数值信息的多种二进制编码方法,多种编码方法其实质都是在对负数的表示进行改造,原码、反码和补码就是这样。
原码:符号-绝对值表示的编码,称为原码。
反码:正数的反码表示与原码表示一样。负数的反码的符号位与原码相同,其余各位按位取反。
补码:正数的补码表示与原码表示一样。负数的补码可由该数的反码再加1求得。
--->补码的好处是:(1)零的表示唯一(2)符号位可作为数值参加运算
对于原码、反码和补码我们得出的结论是:
(1)计算机数值信息的"机器数"采用的是补码,这样可以简化带符号数值的运算
(2)正数的反码和补码和原码相同
(3)负数补码计算方法可以总结为对其相反数"按位求反再加一",其实质就是对负数的相反数求相反数。补码的补码就是原码的相反数
(4)补码参与运算的结果依然是补码
##################################################
附:负数补码计算方法"按位求反再加1"其实质就是求相反数,以下是简明推理过程
以-13机器数的推理为例:
-13=?
-13+13=0
******** + 00001101 = 00000000
******** + 00001101 = 100000000
******** = 100000000 - 00001101
******** = 11111111 + 1 - 00001101
******** = 11111111 - 00001101 + 1
******** = 11110010 + 1
******** = 11110011
试求-51的机器码?
-51=?
-51+51=0
******** + 00110011 = 00000000
******** + 00110011 = 100000000
******** = 100000000 - 00110011
******** = 11111111 + 1 - 00110011
******** = 11111111 - 00110011 + 1
******** = 11001100 + 1
******** = 11001101
##################################################
C语言源程序中向指定存储区存放数据的操作许多,其中赋值操作符是 = 是最核心的,该操作符可以把右操作数赋给左操作数,左操作数应该是一个允许存放数据的存储区。我们把可以放在赋值操作符左边的变量成为左值变量,把可以放在赋值操作符右边的变量称为右值变量。
ANSI C标准库标准输入输出模型中,不管文本从何处输入又或向何处输出都将按照字符流处理,文本流是一个多行字符组成的字符序列,每一行行末都有一个换行符。(PS:往往程序可以通过统计换行符来得到总行数)
C语言源程序中,一个字符串常量应该用双引号""括起来才行!
并且,一般地,一个字符串常量应该置于同一行才可以,因为编译器是不会主动到其他行寻找字符串结束分隔符"的。 (PS:
当然,如果字符串常量被人为分散在多行,应该使用续行符号\来连接两行,以方便编译器认定一个完整的字符串)
1 /* 2 * printf格式控制字符串中转义字符序列\r练习 3 * */ 4 5 #include <stdio.h> 6 7 int main() 8 { 9 long int integer = 0; 10 11 for (integer = 1; integer <= 987654321l; integer++) 12 if (integer % 4 ) 13 printf("."); 14 else 15 printf("\r"); 16 17 return 0; 18 }
1 /* 2 * printf练习 3 * 转义字符序列 4 * */ 5 6 #include <stdio.h> 7 int main() 8 { 9 printf("\"\"\n");//输出引号 10 printf("\\\n");//输出反斜杠 11 printf("%%\n");//输出百分号 12 printf("\a");//输出一个蜂鸣声 13 printf("abc\rxyz\n");//输出abc后退回再输出xyz 14 /*printf("\c\n");//编译会出warning,提示有无法识别的转义字符序列.进一步如果忽略warning,那么\c整体被忽略(也就是说\c根本就没有被编译入机器码)*/ 15 16 printf("%x\n", ‘%‘); 17 printf("\x5\n");//格式控制字符串中可以用转义字符序列来实现通用的字符表达方式,通过使用转义字符序列代表任意字符 18 19 return 0; 20 }
1 /* 2 * 3 * scanf练习 4 * */ 5 6 #include <stdio.h> 7 8 int main() 9 { 10 11 int integer = 0; 12 scanf("%d", &integer); 13 printf("%d\n", integer); 14 15 /* 16 int num = 0; 17 scanf("%d", num);//这样的调用scanf()会引起编译warning 18 //当gcc 02scanf.c -Wall编译时,编译器报warning 19 //如果忽略warning,所生成目标代码执行时候可能引发操作系统强制终止代码执行, 因为代码执行至scanf("%d", num)时,将num当一个地址值使用,这样可能会引起地址越界 20 printf("%d\n", num); 21 */ 22 23 return 0; 24 }
1 /* 2 * 打印C各数据类型当前占有的存储空间大小(byte) 3 * */ 4 5 #include <stdio.h> 6 int main() 7 { 8 printf("int->%d\n", sizeof(int)); 9 printf("unsigned int->%d\n", sizeof(unsigned int)); 10 printf("unsigned->%d\n", sizeof(unsigned)); 11 printf("short int->%d\n", sizeof(short int)); 12 printf("short->%d\n", sizeof(short)); 13 printf("unsigned short int->%d\n", sizeof(unsigned short int)); 14 printf("unsigned short->%d\n", sizeof(unsigned short)); 15 printf("long int->%d\n", sizeof(long int)); 16 printf("long->%d\n", sizeof(long)); 17 printf("unsigned long int->%d\n", sizeof(unsigned long int)); 18 printf("unsigned long->%d\n", sizeof(unsigned long)); 19 printf("char->%d\n", sizeof(char)); 20 printf("unsigned char->%d\n", sizeof(unsigned char)); 21 printf("float->%d\n", sizeof(float)); 22 printf("double->%d\n", sizeof(double)); 23 printf("long double->%d\n", sizeof(long double)); 24 25 return 0; 26 }
1 /* 2 * sizeof()练习 3 * */ 4 #include <stdio.h> 5 6 main() 7 { 8 char character = 0; 9 unsigned char character_u = 0; 10 printf("char类型变量character占有%d个字节\n", sizeof(character)); 11 printf("unsigned char类型变量character_u占有%d个字节\n", sizeof(character_u)); 12 13 /*C语言中我们之所以区分数据类型,就是因为不同数据所占存储空间大小不一*/ 14 printf("char类型变量占有%d个字节\n", sizeof(char)); 15 printf("unsigned char类型变量占有%d个字节\n", sizeof(unsigned char)); 16 }
1 /* 2 * sizeof()练习 3 * sizeof()只是用来计算操作数占有的存储空间,它不影响操作数本身.请分析本例 4 * */ 5 #include <stdio.h> 6 7 main() 8 { 9 char character = 0; 10 11 character = ‘a‘; 12 printf("char类型变量character存放着%c, 占有%d个字节\n",character, sizeof(char)); 13 14 sizeof(character = ‘b‘);//sizeof关键字可以对表达式的结果计算占有存储空间大小,但是表达式中的所有修改都不会保留,所以本例程的两行打印结果一样。 15 printf("char类型变量character存放着%c, 占有%d个字节\n",character, sizeof(char)); 16 }
1 /* 2 * 3 * Discreption:计算87+97演示溢出的例程 4 * 当采用一个字节存储时,87+97会溢出 5 * */ 6 #include <stdio.h> 7 main() 8 { 9 char c = 87; 10 printf("%d\n", c); 11 c = c + 87;//这里会溢出 12 printf("%d\n", c); 13 }
1 /* 2 * 操作符练习 3 * */ 4 5 #include <stdio.h> 6 main() 7 { 8 int num1 = 0, num2 = 0; 9 10 printf("15 / 7 = %d\n", 15 / 7); 11 printf("15 %% 7 = %d\n", 15 % 7); 12 num1 = num2 = 7; 13 printf("num1是%d, num2是%d\n", num1, num2); 14 num1 += 2;//num = num + 2; 15 printf("num1是%d\n", num1); 16 num1 *= 2 + 3;//复合赋值操作符的优先级和赋值操作符的优先级一样,所以语句num *= 2 + 3;等效于语句num = num * (2 + 3); 17 printf("num1是%d\n", num1); 18 19 }