[原创]C语言总结
总算把C语言又看了一遍,总结如下:1. 二制数中原码.反码.补码以及进制之间的转换:
原码:由符号位和该数的绝对值的二进制数组成.
反码:负数的反码为除符号位以外所有位均取反的结果.正数
的反码与原码相同,其补码也一样,后面不说了.
补码:负数的补码是在其反码的基础之上加1;
下面以-123为例求其各码:
原码:符号位为1,二进制数为1111011,(其转换参考下面进制的转换)所以其原码为11111011.
反码:10000100
补码:10000101
进制的转换:
十进制数转其他:
(1):整数:以十进制数123转换为八进制数为例:
123/8=15……3 ----------最低位
15/8=1………7
1/8=0………1 -----------最高位
结果就是173(从下到上),商为0止
(2):小数:0.325转换为二制数为例:
乘2 纯小数部分 整数部分
2 * 0.375=0.750 0.750 0
2 * 0.750=1.5 0.5 1
2 * 0.5 =1.0 0 1
结果就为0.011(从上到下),纯小数为0终止.否则一直进行下去
直到字节数已满.
其它转十进制:以十六进制数A5FE转换十进制数为例:
A5FE=A * 16^3+5 *16^2+F * 16^1+E=42494
二进制数:
十进制数不用说了,转八进制数时,从低位起,每三位对一位,不足补0;转十六进制数,从低位起每四位对一位,不足补0;其它转二进制数是一个相反的过程.
下面举两个例子:
(1);二进制数10101101转八进制数:
010 101 101
| | |
2 5 5
结果就是255
(2):十六进制A69E数转二制数:
A 6 9 E
| | | |
1010 0110 1001 1110
结果就是1010011010011110
2. 变量在内在中的存放与转换.
(1) 存放:
整型数据是转换成相应的补码后直接存放在内存中,而实型与整型的存放不同,它是以指数形式存放,即符号位+小数部分+指数部分.比如:12345在内在中的存放形式是这样的:第一位符号位是’+’,接下来存放的是小数,即0.12345,最后是指数5,而小数部分和指数部分所占的位数因编译系统的不同而不同,不必深究,
(2) 转换:
所有可以转换的数据类型之间的转换都遵循一个规则:按存储单元的存储形式直接传送,从低位开始.比如:将十进制数-123转换为八进制数: 将其补码原样传送由于八进制数无符号(十六进制数也一样),所以最高位的1在八进制数的内在单元中已不代表符号,而代表数值进行运算.不同的编译器和机器所得的结果不一定相同,因为整型变量所占的字节数不同,现以十六位机(另外还与编译器有关,假如整型占两个字节)为例:-123的补码为1111111110000101,将其换算成八进制数为177605,而在32位机上(假如整形占4个字节),其结果就是37777777605.
实型转换成整型时,得到的绝不是你想要的结果,因为实型的存储形式是按指数形式存储的,低位中存储的是指数部分,当传送的时候,只是将指数部分或指数部分加上小数部分的小部分传送给整型变量,得到的结果不可能是你想要的结果.
3.字符----- ‘\’的作用:
与一些字母组成转义字符,比如\t、\n之类的,与数字组成代表八进制数.比如:\123代表八进制数123即十进制数83.另外说明一下\r,其作用是将当前位置移到本行开头,后面再输入字符时,原有的字符将会被覆盖,比如printf(“abcd\r \n“);将会输出” cd”,而不是” abcd”.还有\b也是一样.
4.自增自减:
(1).运算符在前时,先进行运算再进行取值,运算符在后时,先进行取值再进行运算.比如a=++i ;相当于i=i+1;a=i ; ,而a=i++;则相当于a=i;i=i+1;
(2).自增自减运算符不能用于常量 (表达式结果也是常量),只能用于变量.
(3).警告:不要使用+++,---之类的运算符,不同的编译器有不同的结果,也不要在一个式子中对同一变量进行多次++或--,比如:(i++)+(i++)+(i++),同样不同的编译器会得到不同的结果.
5.逗号运算符.
结合方向是自左向右,结果为最后一个表达式的值,其优先级最低.注意函数中的”,”一般是参数分隔符,不是逗号运算符,详情见44楼:
http://bbs.bc-cn.net/dispbbs.asp?boardid=5&replyid=62343&id=124695&page=1&skin=0&star=3
6.退出过程.
(1)continue :用于结束某次循环继续下一循环.
(2)break: 用于结束循环或结束switch语句.
(3)return: 用于结束某函数.
(4)exit: 用于结束某一程序
7.printf("%*s\n",M,"字符串"+N)的用法说明
先看N的值,去掉字符串的左边N个字符,再看字符串的位数与M的值的大小
1.若字符串的位数比M大,然后输出
2.若字符串的位数比M小,就先在M的左边补空格,使字符串的长度等于M,然后输出
printf("%-*s\n",M,"字符串"+N),
先看N的值,去掉字符串的左边N个字符,再看字符串的位数与M的值的大小
1.若字符串的位数比M大,然后输出
2.若字符串的位数比M小,就先在M的右边补空格,使字符串的长度等于M,然后输出
8.scanf函数的用法和说明
(1),指定输入列数,系统自动截取,比如:scanf(“%3d”,&a);输入1234;a=123;
(2).*的用法,跳过指定列数.比scanf(“%2d%*3d%d”,&a,&b);输入1234567,a=12,b=67;345被跳过
(3).输入时不能指定精度
(4).输入数据时要与格式控制保持一致,格式控制中用”,”分开,输入时也要用”,”分开,格式控制中用”:”分开,输入时也要用”:”分开, 否则结果不可预料.如果格式控制中没有用任何字符隔开,你也不要用任何字符隔开,包括空格,比如:scanf(“%c%c”,&a,&b);如果输入a b (中间有空格),此时a=’a’,b=’’,而b却存入缓存中.另外格式控制后是变量地址,普通变量不要忘了取地址运算符”&”.本来代表地址的也不要多加”&”.比如指针(数组名也是指针)不用加”&”.
(5).清除缓存.当缓存中有数据时,使用scanf时,不会提示输入字符,而是直接将缓存中的数据(包括回车符)赋给变量,直到缓存中没有变量.这样就要在调用scanf之前清除缓存,用语句fflush(stdin);来清除缓存.另外用scanf(“ %c”,&a);在格式控制中多加一个空格可以清除一个字符,当有多个字符时就不有完全清除,还可以用 * 来清除缓存,和空格作用差不多,比如:scanf(“%*5c%c”,&a);可以清除缓存中五个字符.最好是直接用fflush (stdin);
9.易错点
(1).if (a=4)…; 相当于a=4;if(4)…;
(2).switch语句要注意break;
(3).do {…} while; 要注意最后一个分号不能丢
(4).不能定义动态数组,比如:scanf (“%d”,&n); int a[n];
10.void的说明.
Void代表空类型,在定义指针变量或函数时可以定义为void型,定义指针变量后可以在用的时候通过强制类型转换使其指向任何类型的数据.定义函数时,只是说明不能有返回值.如果函数中出现return就会报错.
11.局部变量.全局变量
作用域:局部变量的作用域从定义处到该过程(可以是一个复合语句也可以是一个函数)结束.全局变量的作用域从定义处到文件结束.
存在性:局部变量(未声明为static类型)当所在过程被调用时存在,结束后释放,如果定义为static就会一直存在直到程序结束,但其作用域不受影响.全局变量在被定义后就一直存在.直到程序结束.
优先级:当两个相同变量的作用域重复(一个包含另一个),在较小的作用域范围内,较大作用域的那个变量被屏蔽.比如:i被定义为一个全局变量,在其作用域内又定义了一个局部变量i,在局部变量i作用域内,全局变量i被屏蔽.又如.在一个函数中定义了一个局部变量i,而在该函数的某个复合语句中又定义了一个变量i,则在该复合语句中局部变量i将被屏蔽.
12.预编译处理命令
#define:宏定义只是在编译前对代码作简单的字符串替换,不会考虑任何错误.宏定义不是语句,后面不要加";".
#include:
“ ”与< >之前的区别.” “是从用户当前目录寻找包含文件,若找不到就会到库函数所在目录中寻找,再找不到就报错,而< >则是直接在库函数所在目录中寻找,找不到报错.
13.指针:
(1).指针的加减法:指针的加减法不是作简单的加减,而是以指针变量所占的字节数为单位进行加减.
(2).数组名是指针常量,不能改变其值,比如数组a[ ],如果进行a++;就会报错
(3). 虽然指针变量中存放的地址是整型数据,但不能将整型数据直接赋值给指针变量,应该这样(假如p为int *型),p=(int *)1000;但禁用些法,因为你不知道1000这个单元有没有被其它单元占用,后果不可预料,同样也不能将一个指针变量的值直接赋给整形变量,也要进行强制类型转换.
(4)定义指针后,在使用之前一定要先给它赋初值,切记
(5).二维数组中指针问题(int a[3] [4]),数组名a是一个指向行的指针(指向数组),而在其前面加一个 * ,*a就是指向列的指针(指向无素).a与*都是指向a[0][0];但a+1(行指针)指向a[1][0];而*a+1(列指针,和*(a+0)+1一样)却指向a[0][1];同样在a+1前加一个*就又变成列指针了,*(a+1)+2就指向a[1][2].
(6),复杂类型的说明:从变量名处起,根据运算符优先级结合,一步一步分析,下面以一个比较复杂的类型( int * (*p(int))[ ] )为例:
第一步,p先与()结合,说明是一个函数,第二步,()内有一个int,说明函数有一个形参为int型,第三步与*结合,说明返回的是一个指针变量,第四步与[ ]结合,说明该指针变量指向数组,第五步再与*结合,说明数组中的元素为指针型,第六步说明数组中的指针元素的类型为int型,完毕,所以这是一个返回一个由整型指针变量组成的数组的指针变量的函数.
14枚举类型:
枚举元素为常量,只有在定义的时候能对它们进行赋值(不赋值时,系统给它们赋值,从0开始递增),在其它时候均不能进行赋值,
大家有好的经验发上来,我加到里面去,如有错误请指示
[此贴子已经被作者于2007-4-30 19:43:14编辑过]