C语言基础
一、 常量与变量
1.1 常量
在程序运行过程中,其值不能被改变的量称为常量。
1)整形常量
如100 ,22,-109等都是整形常量。
2)实型常量
1)十进制小数形式,由数字和小数点组成。如123. 456,0. 345,- 56.79,0.0,12.0等。
2)指数形式,如12. 34e3(代表12. 34X103),0.145E- 25(代表0. 145X10-25)等。由于在计算机输人或输出时无法表示上角或下角,故规定以字母e或E代表以10为底的指数。但应注意: e或E之前必须有数字,且e或E后面必须为整数。如不能写成e4,12e2. 5。
3)字符常量
1)普通字符
用单撇号括起来的一个字符,如:‘a’,‘Z’,‘3’,’?’,’#’。不能写成’ab’或12’。 请注意:单撇号只是界限符,字符常量只能是一个字符,不包括单撇号。‘a’和’ A’是不同的字符常量。字符常量存储在计算机存储单元中时,并不是存储字符(如a,z,#等)本身,而是以其代码(一般采用ASCII代码)存储的,例如字符a’的ASCII代码是97,因此,在存储单元中存放的是97(以二进制形式存放)。
下面是ASCII 字符与代码对照表
2)转义字符
例如,前面已经遇到过的,在printf 函数中的\n’代表一个“换行”符。\t代表将输出的位置跳到下一个Tab位置(制表位置),一个Tab位置为8列。这是一种在屏幕上无法显示的“控制字符”,在程序中也无法用一个一般形式的字符来表示,只能采用这样的特殊形式来表示。
下面是转义字符及其作用
转义字符 | 字符值 | 输出结果 |
---|---|---|
\ ’ | 一个单撇号( ’ ) | 输出单撇号字符 |
\ " | 一个双撇号(") | 输出双撇号字符” |
? | 一个问号(?) | 输出问号字符? |
\ \ | 一个反斜线( \ ) | 输出反斜线字符\ |
\ a | 警告(alert) | 产生声音或视觉信号 |
\b | 退格( backspace) | 将光标当前位置后退一个字符 |
\f | 换页(form feed) | 将光标当前位置移到下一页的开头 |
\ n | 换行 | 将光标当前位置移到下一-行的开头 |
\r | 回车(carriage return) | 将光标当前位置移到本行的开头 |
\t | 水平制表符 | 将光标当前位置移到下一个Tab位置 |
\v | 垂直制表符 | 将光标当前位置移到下一个垂直制表对齐点 |
\o,\oo或\ooo其中o代表一个八进制数字 | 与该八进制码对应ASCII字符 | 与该八进制码对应的字符 |
\xh[h…]其中h代表一个十六进制数字 | 与该十六进制码对应的ASCII 字符 | 与该十六进制码对应的字符 |
4)字符串常量
如"boy" ,"123"等,用双撇号把若干个字符括起来,字符串常量是双撇号中的全部字符(但不包括双撇号本身)。注意不能错写成’CHINA’,‘boy’,‘123’。单撇号只能包含一个字符,双撇号中可以包含一个字符串。
5)符号常量
用#define指令,指定用一个符号名称代表一个常量
# define PI 3. 1416
经过以上的指定后,本文件中从此行开始所有的PI都代表3. 1416。在对程序进行编译前,预处理器先对PI进行处理,把所有PI全部置换为3. 1416。这种用一个符号名代表一个常量的,称为符号常量。在预编译后,符号常量已全部变成字面常量(3.1416)。
1.2 变量
1)变量的声明
变量代表一个有名字的、具有特定属性的一个存储单元。 它用来存放数据,也就是存放变量的值。在程序运行期间,变量的值是可以改变的.变量必须先定义,后使用,一个变量应该有一个名字,以便被引用。请注意区分变量名和变量值
这两个不同的概念,下面介绍了
变量名实际上是以一个名字代表的一个存储地址。在对程序编译连接时由编译系统给每-一个变量名分配对应的内存地址。从变量中取值,实际上是通过变量名找到相应的内存地址,从该存储单元中读取数据。
2)赋值和初始化
1)赋值
int s=10;
这里我们用到了“=”,它表示把右边的值赋给左边的变量。
2)初始化
int a,b;
程序输出的a,b的值很奇怪,这是因为在生成变量的时候,变量会被放入一个不确定的值,即垃圾值
注根据运行环境和编译器的不同,显示的值也不同(有时会发生运行时错误,导致程序运行中断)。即使是相同的运行环境,每次执行程序时也有可能显示的值都有所不同
二、 运算符与表达式
2.1 运算符
1)C运算符
C语言提供了以下运算符:
运算符 | 符号 |
---|---|
算术运算符 | (+一*/.%+±-) |
关系运算符 | (==>=<= !=) |
逻辑运算符 | (! && II ) |
位运算符 | (<< >> ~ I &) |
赋值运算符 | (=及其扩展赋值运算符) |
条件运算符 | (?: ) |
逗号运算符 | (,) |
指针运算符 | ( *和&) |
求字节数运算符 | (sizeof) |
强制类型转换运算符 | ( (类型) ) |
成员运算符 | (,->) |
下标运算符 | ([ ]) |
其他 | (如函数调用运算符()) |
2)算术运算符
运算符 | 描述 | 实例 |
---|---|---|
+ | 把两个操作数相加 | A + B 将得到 30 |
- | 从第一个操作数中减去第二个操作数 | A - B 将得到 -10 |
* | 把两个操作数相乘 | A * B 将得到 200 |
/ | 分子除以分母 | B / A 将得到 2 |
% | 取模运算符,整除后的余数 | B % A 将得到 0 |
++ | 自增运算符,整数值增加 1 | A++ 将得到 11 |
– | 自减运算符,整数值减少 1 | A-- 将得到 9 |
注(++),(- -)运算符
#include<stdio.h>
int main()
{
int c;
int a = 10;
c = a++;
printf("先赋值后运算:\n");
printf("Line 1 - c 的值是 %d\n", c );
printf("Line 2 - a 的值是 %d\n", a );
a = 10;
c = a--;
printf("Line 3 - c 的值是 %d\n", c );
printf("Line 4 - a 的值是 %d\n", a );
printf("先运算后赋值:\n");
a = 10;
c = ++a;
printf("Line 5 - c 的值是 %d\n", c );
printf("Line 6 - a 的值是 %d\n", a );
a = 10;
c = --a;
printf("Line 7 - c 的值是 %d\n", c );
printf("Line 8 - a 的值是 %d\n", a );
}
结束应该是
先赋值后运算:
Line 1 - c 的值是 10
Line 2 - a 的值是 11
Line 3 - c 的值是 10
Line 4 - a 的值是 9
先运算后赋值:
Line 5 - c 的值是 11
Line 6 - a 的值是 11
Line 7 - c 的值是 9
Line 8 - a 的值是 9
原因是++i,- -i (在使用i之前,先使i的值加(减)1) i++,i-- (在使用i之后,使i的值加(减)1)
3)关系运算符
下表显示了 C 语言支持的所有关系运算符。假设变量 A 的值为 10,变量 B 的值为 20,则:
运算符 | 描述 | 实例 |
---|---|---|
== | 检查两个操作数的值是否相等,如果相等则条件为真。 | (A == B) 不为真。 |
!= | 检查两个操作数的值是否相等,如果不相等则条件为真 | (A != B) 为真。 |
> | 检查左操作数的值是否大于右操作数的值,如果是则条件为真 | (A > B) 不为真。 |
< | 检查左操作数的值是否小于右操作数的值,如果是则条件为真。 | (A < B) 为真。 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 | (A >= B) 不为真。 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 | (A <= B) 为真。 |
4)逻辑运算符
下表显示了 C 语言支持的所有关系逻辑运算符。假设变量 A 的值为 1,变量 B 的值为 0,则:
运算符 | 描述 | 实例 |
---|---|---|
&& | 称为逻辑与运算符。如果两个操作数都非零,则条件为真。 | (A && B) 为假。 |
II | 称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。 | (AII B) 为真。 |
! | 称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。 |
5)位运算符
位运算符作用于位,并逐位执行操作。&、 | 和 ^ 的真值表如下所示:
p | q | p & q | p I q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
假设如果 A = 60,且 B = 13,现在以二进制格式表示,它们如下所示:
A = 0011 1100
B = 0000 1101
A&B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
~A = 1100 0011
下表显示了 C 语言支持的位运算符。假设变量 A 的值为 60,变量 B 的值为 13,则:
运算符 | 描述 | 实例 |
---|---|---|
& | 按位与操作,按二进制位进行"与"运算。 | 运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1; (A & B) 将得到 12,即为 0000 1100 |
I | 按位或运算符,按二进制位进行"或"运算。 | 运算规则:0I 0=0; 0I 1=1; 1I 0=1; 1I 1=1; |
^ | 异或运算符,按二进制位进行"异或"运算 | 运算规则:0^0=0; 0^1=1; 1^0=1; 1^1=0; (A ^ B) 将得到 49,即为 0011 0001 |
~ | 取反运算符,按二进制位进行"取反"运算。 | 运算规则:~1=0; ~0=1; (~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式。 |
<< | 二进制左移运算符。 | 将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。 A << 2 将得到 240,即为 1111 0000 |
>> | 二进制右移运算符。 | 将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。 A >> 2 将得到 15,即为 0000 1111 |
6)赋值运算符
下表列出了 C 语言支持的赋值运算符:
运算符 | 描述 | 实例 |
---|---|---|
= | 简单的赋值运算符,把右边操作数的值赋给左边操作数 | C = A + B 将把 A + B 的值赋给 C |
+= | 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 | C += A 相当于 C = C + A |
-= | 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 | C -= A 相当于 C = C - A |
*= | 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 | C *= A 相当于 C = C * A |
/= | 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 | C /= A 相当于 C = C / A |
%= | 求模且赋值运算符,求两个操作数的模赋值给左边操作数 | C %= A 相当于 C = C % A |
<<= | 左移且赋值运算符 | C <<= 2 等同于 C = C << 2 |
>>= | 右移且赋值运算符 | C >>= 2 等同于 C = C >> 2 |
&= | 按位与且赋值运算符 | C &= 2 等同于 C = C & 2 |
^= | 按位异或且赋值运算符 | C ^= 2 等同于 C = C ^ 2 |
I= | 按位或且赋值运算符 | C I= 2 等同于 C = C I 2 |
7)杂项运算符 ↦ sizeof & 三元
运算符 | 描述 | 实例 |
---|---|---|
sizeof() | 返回变量的大小。 | sizeof(a) 将返回 4,其中 a 是整数。 |
& | 返回变量的地址。 | &a; 将给出变量的实际地址。 |
* | 指向一个变量。 | *a; 将指向一个变量。 |
? : | 条件表达式 | 如果条件为真 ? 则值为 X : 否则值为 Y |
8)C 中的运算符优先级
类别 | 运算符 | 结合性 |
---|---|---|
后缀 | () [] -> . ++ - - | 从左到右 |
一元 | + - ! ~ ++ - - (type)* & sizeof | 从右到左 |
乘除 | * / % | 从左到右 |
加减 | + - | 从左到右 |
移位 | << >> | 从左到右 |
关系 | < <= > >= | 从左到右 |
相等 | == != | 从左到右 |
位与 | AND & | 从左到右 |
位异或 | XOR ^ | 从左到右 |
位或 | ORI | 从左到右 |
逻辑与 | AND && | 从左到右 |
逻辑或 | ORII | 从左到右 |
条件 | ?: | 从右到左 |
赋值 | = += -= *= /= %=>>= <<= &= ^= I = | 从右到左 |
逗号 | , | 从左到右 |
三、C语句
3.1控制语句
控制语句用于完成一定的控制功能
形式 | 类型 |
---|---|
条件语句 | if()…else… |
循环语句 | for()… |
循环语句 | while()… |
循环语句 | do…while () |
结束本次循环语句 | continue |
中止执行switch或循环语句 | break |
多分支选择语句 | switch |
从函数返回语句 | return |
转向语句,在结构化程序中基本不用goto语句 | goto |
举个栗子
上面的“if()…else……”的具体语句可以写成
if(x >y) z=x; else z=y;
其中,x>y是一个“判别条件”,“z=x;”和“z=y;”是C语句,这两个语句是内嵌在if…else语句中的。这个if…else语句的作用是:先判别条件“x>y”是否成立,如果x>y成立,就执行内嵌语句“z=x;”。,否则就执行内嵌语句"z=y".在后面我们会具体详细地介绍控制语句的用法。
3.2赋值语句
1)数据类型与运算
我们来看一下下面的运算结果
像1和2这样类型相同的操作数之间的运算,所得到的数据类型和运对象的数据类型是一致的,像3和4这样类型时会进行隐式类型转换
那如果是将一个占字节多的整型数据赋给一个占字节量少的short会发生什么呢?
int i=289; char='a' c=i;
;
由于char占一个字节所以在赋值时发生截断
2)赋值表达式和赋值语句>
赋值表达式既然是表达式,那么它就可以出现在其他表达式之中例如:
if ((a=b)>0)max= a;
按一般理解,if后面的括号内应该是一个“条件”,例如可以是if (a>0) max= a;
现在,在a的位置上换上一个赋值表达式a=b,其作用是:先进行赋值运算(将b的值赋给a),然后判断a是否大于0,如大于0,执行max=a。请注意,在if语句中的a=b不是赋值-语句,而是赋值表达式)如果写成if ((a=b;)>0) max=a;//“a= b;”是赋值语句
就错了。在if的条件中可以包含赋值表达式,但不能包含赋值语句.
四、输入和输出
4.1 标准文件
C 语言把所有的设备都当作文件。所以设备(比如显示器)被处理的方式与文件相同。以下三个文件会在程序执行时自动打开,以便访问键盘和屏幕。
标准文件 | 文件指针 | 设备 |
---|---|---|
标准输入 | stdin | 键盘 |
标准输出 | stdout | 屏幕 |
标准错误 | stderr | 您的屏幕 |
C 语言中的 I/O (输入/输出) 通常使用 printf() 和 scanf() 两个函数。
scanf() 函数用于从标准输入(键盘)读取并格式化, printf() 函数发送格式化输出到标准输出(屏幕)。
1)所有的 C 语言程序都需要包含 main() 函数。 代码从 main() 函数开始执行。
2)printf() 用于格式化输出到屏幕。printf() 函数在 “stdio.h” 头文件中声明。
3)stdio.h 是一个头文件 (标准输入输出头文件) and #include 是一个预处理命令,用来引入头文件。 当编译器遇到 printf() 函数时,如果没有找到 stdio.h 头文件,会发生编译错误。
4)return 0; 语句用于表示退出程序。
4.2printf() 函数
1)printf函数一般形式
2)格式字符
1)d格式符
输出一个有符号的十进制整数
可以在格式声明中指定输出数据的域宽(所占的列数),如用“%5d”,指定输出数据占5列,输出的数据显示在此5列区域的右侧。如:printf("%5d\n%5d\n" ,12,- 345);
输出结果为
12(12前面有3个空格)
一345(一345前面有1个空格)
若输出long(长整型)数据,在格式符d前加字母1(代表long),即“%ld”。若输出long long(双长整型)数据,在格式符d前加两个字母II(代表longlong),即“%lld”。
2)c格式符
用来输出一个字符
char ch= 'a' ;printf("%c" ,ch);
运行时输出a
-一个整数,如果在0~127范围中,也可以用“%c”使之按字符形式输出,在输出前,系统会将该整数作为ASCII码转换成相应的字符;如short a= 121;printf(" %c ,a);
输出字符y
如果整数比较大,则把它的最后一个字节的信息以字符形式输出。如int a= 377; printf("%c" ,a);
也输出字符y,因为用%c格式输出时,只考虑一个字节,存放a的存储单元中最后一个字节中的信息是01111001,即十进制的121,它是’y’的ASCII代码。
3) s格式符
用来输出一个字符串
4)f格式符
用来输出实数(包括单、双精度长双精度),以小数形式输出,有几种用法:
1)基本型,用%f
不指定输出数据的长度,由系统根据数据的实际情况决定数据所占的列数。系统处理的方法一般是:实数中的整数部分全部输出,小数部分输出6位。
2)指定数据宽度和小数位数,用%m.nf。
我们把上面的输出变一下
3)输出的数据向,左对齐用%-m.nf
在m.n的前面加一个负号,其作用与%m.nf形式作用基本相同,但当数据长度不超过m时,数据向左靠,右端补空格。如:
第1次输出a时输出结果向左端靠,右端空5列。第2次输出a时输出结果向右端靠,左端空5
列。
5)e格式
用格式声明%e指定以指数形式输出实数,数值按标准化指数形式输出
5)printf函数用的格式字符
格式字符 | 说明 |
---|---|
%d | 按整型数据的实际长度输出。 |
%md | m为指定的输出字段的宽度。 |
%ld | 输出长整型数据。 |
o | 以八进制整型式输出整数。 |
x | 以十六进制数形式输出整数。 |
u | 用来输出unsigned型数据,即无符号数,以十进制形式输出。 |
c | 用来输出一个字符。 |
s | 用来输出一个字符串。 |
f | 用来输出实数(包括单双精度),以小数形式输出。 |
e | 以指数形式输出实数。 |
g | 用来输出实数,它根据数值的大小,自动选f格式或e格式(选择输出是占宽度较小的一种),且不输出无意义的零。 |
p | 用于变量地址的输出。 |
4.3scanf函数
注意
1)scanf 函数中的格式控制后面应当是变量地址,而不是变量名
2)如果在格式控制字符串中除了格式声明以外还有其他字符,则在输人数据时在对应的位置上应输人与这些字符相同的字符。
3)在用“%c”格式声明输人字符时,空格字符和“转义字符”中的字符都作为有效字符输入
4))在输人数值数据时,如输人空格、回车.Tab键或遇非法宇字符(不属于数值的字符)认为该数据结束。
4.4getchar() & putchar() 函数
int getchar() 函数从屏幕读取下一个可用的字符,并把它返回为一个整数。这个函数在同一个时间内只会读取一个单一的字符。您可以在循环内使用这个方法,以便从屏幕上读取多个字符。
int putchar(int c) 函数把字符输出到屏幕上,并返回相同的字符。这个函数在同一个时间内只会输出一个单一的字符。您可以在循环内使用这个方法,以便在屏幕上输出多个字符。
五、END
谢谢大家阅读,点个赞吧