C语言基础学习笔记
(第一版修改)
丁炳亮
1数据类型和表达式
1.1计算机内数据存储方式
理解与测试:
计算机内部所有的数据都是以二进制的形式存储的。我们平常使用的有理数都是分正负数的,在计算机内部整型是通过最高位区分正负数,负数的最高位为1。如果直接用这种表达方式进行运算,那么运算前要先判断是无符号数还是有符号数,因为有符号数的最高位是符号位不能直接参与运晕,并且减法运算还得有专门的减法器。为了能把符号位参与运算且加法和减法能够统一处理我们用到了补码。
什么是补码?我们得先知道模的概念。模“模”是指一个计量系统的计数范围。如时钟等。计算机也可以看成一个计量机器,它也有一个计量范围,即都存在一个“模”。例如:
时钟的计量范围是0~11,模=12。表示n位的计算机计量范围是0~2^(n)-1,模=2^(n)。
“模”实质上是计量器产生“溢出”的量,它的值在计量器上表示不出来,计量器上只能表示出模的余数。任何有模的计量器,均可化减法为加法运算。例如:假设当前时针指向10点,而准
确时间是6点,调整时间可有以下两种拨法:一种是倒拨4小时,即:10-4=6;另一种是顺拨8小时:10+8=12+6=6在以12模的系统中,加8和减4效果是一样的,因此凡是减4运算,都可以用加8来代替。对“模”而言,8和4互为补数。实际上以12模的系统中,11和1,10和2,9和3,7和5,6和6都有这个特性。共同的特点是两者相加等于模。
二进制中整数的补码求法是:正数的补码为原码,负数的补码是符号位不变其他位全部取反再整个数加1。我们可以通过下面的代码看下负整数在计算机内部的表示。
void f(int n)
{
unsigned int i;
for(i=1,i<<=15;i;i>>=1)
{
if(i&n)
printf("1");
else
printf("0");
}
printf("\n");
}
main()
{
int a=-0xff;
f(a);
getch();
}
输出的结果是1111111100000001。
1.2变量与常量
理解与测试:
1)类型声明
在计算机内部数据是以字节为单位存储的,但是我们需要的数据类型有很多种,每种数据类型所占字节和存储方式都不一样。类型声明的作用就是告诉计算机以哪种“格式”去读写该数据数据。
类型说明符 变量名1,变量名2......,变量名n;
switch的用法c语言类型说明符有基本类型(字符型、整数型、单/双精度型)、高级类型(结构体型、共用体型、枚举类型)、指针型等,其中指针类型包括指向基本类型的指针类型、指向高级类型的指针型和指向函数的指针类型(指向函数指针声明格式在后面章节)。
2)符号常量的定义
#define 标识符 常量;
使用该种方法定义符号常量一个是可以使代码便于阅读理解,另一个是方便代码内部多个相同常量的统一修改。
总结与注意
在写计算式的时候要考虑变量是否会越界。一般来说计算式子时是先强制转换成式子中最大存储空间的数据类型(不包括被赋值的变量),还要注意不同的类型数据在不同的编译器中所占的内存有可能是不一样的,例如有些编译器整型是占2个字节有些是占4个字节。同时还要考虑到符号的优先级和结合顺序,如果按符号的优先级和结合顺序运算过程中有越界的那么整个计算结果可能和预想的不一样了,例如int i=100;i = 500*i/i;最后i=-155。
1.3输出输入
理解与测试:
1)格式化输入输出函数可以按设定的格式和设定的数据类型接收和输出多个变量。控制格式和数据类型的是数据控制符。
2)字符和字符串可以用专门的输出\输入函数。主要有getch(); putch();getchar(); putchar(); gets(); puts();其中getch()和putch()是conio.h中声明,getch()不需要等待回车键就返回字符并立即执行下面一语句符,getch()不在屏幕显示输入的字符。getchar();putchar(); 在stdio.h中声明。getchar()读取键盘上的一个字符,立即返回并显示在屏幕上,需要等待回车键才能执行下一条语句。例如下面的代码:
int main(void)
{
char ch,i;
for(i=0;i<10;i++)
{
ch = getchar();
putchar(ch);
}
getch();
}
输入:I LOVE YOU
输出:I LOVE YOU
总结与注意
格式输入函数中的参数是变量存放的地址,所以变量前面要”&”符号。如果是数组则可以直接用数组名,因为数组名就是指向该数组首地址的指针常量。
1.4运算符号
理解与测试:
1)表达式中符号的运算顺序是有先后的,根据符号的优先级和结合性(左结合/右结合)来判定。如果是几个符号连在一起C内部是怎么去读的呢?有一个很简单的规则:每一个符号应该包含尽可能多的字符。也就是说,编译器读取符号的方法是,从左到右一个字符一个字符地读入,如果该字符可能组成一个符号,那么在读入下一个字符,直到与下个字符组合成的符号没有意义为止。例如:a---b;这个表达式等效于(a--)-b;
2)复合赋值符及表达式在赋值符“=”之前加上其他双目运算符号可以构成复合赋值符。如:+=、-=、*=、/=、%=。构成复合赋值表达式的一般格式为
变量 双目运算符 = 表达式
等价于
变量 = 变量 运算符 表达式
可以这么去理解,等号左边的相当于变量自增、自减、自除、自取余一个数,这个数由右边的表达式计算得到。如:int a=7,b=3,c=3;a+=b+=c+=5;运算后是a=18,b=11,c=8。
3)C中唯一一个三目运算符是条件运算符,由“?”和“:”构成。两个符号必须按下面的格式一起使用:
表达式 1?表达式2:表达式3
三个表达式可以是任意的合法表达式,条件运算符的运算规则如下:如果表达式1的值为真,那么整个表达式的值为表达式2的值,否则为表达式3的值。
4)sizeof()也是一个运算符号,它可以对一个数据类型或一个变量取类型长度。但是当一个数组名作为一个实参传递给函数时,在函数内部是不能用sizeof来获取该数组的长度的。因为数组名是一个指向数组首地址的指针,使用sizeof只能取得实参指针类型长度。
5)比较少用到的符号是“:”和“,”。冒号运算符在C中有三种用途,第一种是我们上面讲到的与“?”构成三目运算。第二种是在switch中放在常量表达式后面。第三种用法是在结构体中定义位域时用到。
struct 位域结构名
{ 位域列表 };
其中位域列表的形式为: 类型说明符 位域名:位域长度
例如:
struct bs
{
int a:8;
int b:2;
int c:6;
};
逗号运算符的功能是把两个表达式连在一起组成一个新的表达式,称为逗号表达式。其一般格式为
表达式1,表达式2,表达式3,...,表达式n;
其求值过程是自左向右求两个表达式的值,并以最后一个表达式的值作为整个逗号表达式的值。例如for(a=0,b=0,c=0;b<10,a<20;b++,a++)++c;运算后c=20,如果把中间的两个语句前后调换for(a=0,b=0,c=0;b<10,a<20;b++,a++)++c;运算后c=10。
6)不同的数据类型的量混合运算的时候,系统会临时把算式中长度小的数据类型自动转换成长度大的数据类型。在某些时候我们需要临时改变一个数据的类型或者说是读取“格式”,我们可以使用强制类型转换符,”(type)”。使用的格式一般如下:
(类型说明符)表达式
要得到一个数据类型的类型说明符很容易。只要知道如果声明一个给定类型的变量,那么就可以得到该数据类型的转换符就是把声明中变量名和声明的分号去掉。例如:(int)、(float)、(char *)、(int(*)())等等。
总结与注意
1)“==”和“=”这两个符号也容易在判断语句内出错,严重的还会出现死循环。
2)自增“++”和自减“--”可以作为前缀也可以作为后缀。作为变量前缀时,在表达式中每次取用变量值运算前先自增/自减,作为变量后缀时,在表达式中每次取用变量值运算后再自增/自减。例如:
main()
{
int i=2,j=1,n;
printf("%d\n",i++);
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论