第三章 数据类型、运算符和表达式
声明
本文内容大多取自《高级语言程序设计一书》,为本人学习笔记记录,切勿用于商业用途。
第一节 数据类型
数据既是程序加工和处理的对象,也是程序加工和处理的结果。
C 语言提供了丰富的数据类型,
其中:
1)基本类型包括整型、实型(又称浮点型)、字符型和枚举型四种。
2)构造类型是由基本数据类型按一定规则组合而成的复杂数据类型,包括数组型、结构体类型 和共用体类型。其中,数组型是由相同类型的数据组合而成的,例如若干名学生的成绩组合在一起, 就是一个实型数组;结构体类型是由不同类型的数据组合而成的,例如一个学生的姓名(字符串)、 性别(字符型)、年龄(整型)、成绩(实型)组合在一起,构成一个结构体类型数据。
3)指针类型是一种更加灵活的数据类型,用来表示内存地址。指针类型的数据可以表示基本类 型数据的地址,也可以表示结构体类型数据中第一个数据的地址(又称为首地址)和其中某个具体 数据的地址。
4)空类型是从语法完整性角度给出的数据类型,表示不需要数据值,因而没有类型。
C 语言规定在使用一个数据之前,必须定义数据的类型
,因为数据类型决定了数据占用内存的 字节数、取值范围以及在其上可以进行的操作等
。例如不同类型的数据所占用的内存字节数(又称 为数据长度)是不同的,意味着程序在内存中为不同类型的数据分配不同的字节数,以存放该数据。
C 语言的数据有常量和变量之分,它们分别属于上述的类型。
整数类型
下表列出了关于标准整数类型的存储大小和值范围的细节:
为了得到某个类型或某个变量在特定平台上的准确大小,您可以使用 sizeof 运算符。表达式 sizeof(type) 得到对象或类型的存储字节大小。下面的实例演示了获取 int 类型的大小:
#include <stdio.h>
#include <limits.h>
int main()
{
printf("int 存储大小 : %lu \n", sizeof(int));
return 0;
}
第二节 常量
常量又称为常数,是在程序运行过程中其值不能改变
的数据。
常量可以有不同的类型,C 语言规定常量包括整型常量
、实型常量
、字符型常量
、字符串常量
和符号常量
。使用常量时,不需要事先定义,只需在程序中直接写出。常量的类型,系统可通过书 写形式自动识别,无须定义。
整型常量: 整型常量通常称为整数,不带有小数部分,包括正整数、负整数和0。 C语言中,整型常量有三种书写形式:
1、八进制整型常量,必须以0开头,即以0作为八进制整数的前缀,是由数字 0~7组成的数字串。
2、十进制整型常量,即通常的整数,没有前缀,是由数字0~9组成的数字串, 是C语言中用的最多的一种形式。
3、十六进制整型常量,必须以0X或0x开头,即以0X或0x作为十六进制整 数的前缀,是由字符0-9、a-f或A-F组成的字符串。
补充:
前缀指定基数:0x 或0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制。
整数常量也可以带一个后缀,后缀是 U 和 L 的组合,
U 表示无符号整数(unsigned),L 表示长整数(long)。
后缀可以是大写,也可以是小写,U 和 L 的顺序任意。
下面列举几个整数常量的实例:
212 /* 合法的 */
215u /* 合法的 */
0xFeeL /* 合法的 */
078 /* 非法的:8 不是八进制的数字 */
032UU /* 非法的:不能重复后缀 */
以下是各种类型的整数常量的实例:
85 /* 十进制 */
0213 /* 八进制 */
0x4b /* 十六进制 */
30 /* 整数 */
30u /* 无符号整数 */
30l /* 长整数 */
30ul /* 无符号长整数 */
实型常量(浮点型常量)
实型常量又称为浮点型常量或实数
,实型常量只使用十进制。
C语言的实型常量有两种书写形式:
1、十进制小数形式,由整数部分、小数点和小数部分组成,其中小数点必须 有,整数部分和小数部分可以省略其中一个,正、负通过前面的“+”(可以 省略)和“-”区分。(0.0345)
2、指数形式(用E或e表示),由尾数部分、阶码标志(小写字母e或大写字 母E)和指数部分组成,其一般形式为aEb或aeb,其中尾数部分a的位数决 定了数值的精度,指数部分b的位数决定了可表示的数值范围。a和b均有正 负之分,且b必须为整数。(3.4e-2)
通常,实型常量在 PC 中占用 4 字节(float 4字节,double 8字节),无论是十进制小数形式还是指数形式,其值域为-1038 〜1038,有效数字是 7 位。
浮点常量由整数部分、小数点、小数部分和指数部分组成。
您可以使用小数形式或者指数形式来表示浮点常量。
当使用小数形式表示时,必须包含整数部分、小数部分,或同时包含两者。
当使用指数形式表示时, 必须包含小数点、指数,或同时包含两者。
带符号的指数是用 e 或 E 引入的。
下面列举几个浮点常量的实例:
3.14159 /* 合法的 */
314159E-5L /* 合法的 */
510E /* 非法的:不完整的指数 */
210f /* 非法的:没有小数或指数 */
.e55 /* 非法的:缺少整数或分数 */
字符常量
字符常量包括普通字符常量和转义字符常量两种。
C语言规定字符常量中的字母是区分大小写的。 每个字符常量在内存中占用1字节,具体存放的是该字符对应的ASCII码值。
字符常量是括在单引号中,例如,‘x’ 可以存储在 char 类型的简单变量中。
例如‘a’
、‘?’
转义字符常量,以反斜杠“\”
开头,它只代表某一特定的ASCII码字符。
在 C 中,有一些特定的字符,当它们前面有反斜杠时,它们就具有特殊的含义,被用来表示如换行符(\n)或制表符(\t)等。下表列出了一些这样的转义序列码:
\\ \ 字符
\' ' 字符
\" " 字符
\? ? 字符
\a 警报铃声
\b 退格键
\f 换页符
\n 换行符
\r 回车
\t 水平制表符
\v 垂直制表符
\ooo 一到三位的八进制数
\xhh . . . 一个或多个数字的十六进制数
下面的实例显示了一些转义序列字符:
#include <stdio.h>
int main()
{
printf("Hello\tWorld\n123\n456\n");
return 0;
}
需要注意的是,C语言中空字符和空格符号不同。
空字符用转义字符“\0”表示,其 值是0;
空格符号是ASCII字符集中的一个可显示字符,其ASCII值是32,在屏幕上显示空格。
字符串常量
字符串常量又称为“字符串”,是用双引号括起来的零个或多个字符的序列。
字符串中字符的个数称为字符串长度.
编译时自动在字符串的末尾处加一个转义字符‘\0’作为字符串的结束标志,即长 度为n个字符的字符串占用n+1字节。
下面的实例显示了一些字符串常量。下面这三种形式所显示的字符串是相同的。
"hello, dear"
"hello, \
dear"
"hello, " "d" "ear"
字符常量与字符串常量是不同的,其区别在于:
1、定界符不同,字符常量使用单引号,而字符串常量使用双引号。
2、长度不同,字符常量的长度固定为1;而字符串常量的长度,可以是0,也可以 是某个整数。
3、存储要求不同,字符常量存储的是字符的ASCII码值,在内存中只占用1字节; 而字符串常量,除了要存储有效的字符外,还要存储一个字符串结束标志‘\0’。
符号常量
符号常量使用之前必须先定义,其定义的一般格式
#define 符号常量 常量
#define PI 3.14159
常量可以是任意类型。 符号常量一般采用大写字母表示,而变量一般采用小写字母表示。 符号常量的定义一般放在程序的开头,每个定义必须独占一行,因为不是语句,所 以后面没有分号“;”
使用符号常量的优势在于:
1、提高程序的可读性
2、便于程序修改
定义常量
在 C 中,有两种简单的定义常量的方式:
使用 #define 预处理器。
使用 const 关键字。
下面是使用 #define 预处理器定义常量的形式:
#define identifier value
具体请看下面的实例:
#include <stdio.h>
#define LENGTH 10
#define WIDTH 5
#define NEWLINE '\n'
int main()
{
int area;
area = LENGTH * WIDTH;
printf("value of area : %d", area);
printf("%c", NEWLINE);
return 0;
}
const 关键字
您可以使用 const 前缀声明指定类型的常量,如下所示:
const type variable = value;
const 声明常量要在一个语句内完成:
具体请看下面的实例:
#include <stdio.h>
/*#define LENGTH 10
#define WIDTH 5
#define NEWLINE '\n'*/
int main()
{
const int LENGTH=10;
const int WIDTH=5;
const char NEWLINE='\n';
int area;
area = LENGTH * WIDTH;
printf("value of area : %d", area);
printf("%c", NEWLINE);
return 0;
}
第三节 变量
定义:其值可以改变的量。
定义格式:数据类型 变量名(type variable_list;)
变量应该有名字,并在内存中占据一定的存储单元。
变量名和变量值有不同的含义。
变量是在程序运行过程中,其值可以改变的数据。变量具有三种属性,即: (1)变量名
(2)变量值
(3)变量类型
在这里,type 必须是一个有效的 C 数据类型,可以是 char、w_char、int、float、double 或任何用户自定义的对象,variable_list 可以由一个或多个标识符名称组成,多个标识符之间用逗号分隔。下面列出几个有效的声明:
int i, j, k;
char c, ch;
float f, salary;
double d;
整型变量
整型变量分为四种:
1、基本整型,类型关键字为int。
2、短整型,类型关键字为short[int]。
3、长整型,类型关键字为long[int]。
4、无符号整型,又称为无符号基本整型(unsigned [int])、无符号短整型 (unsigned short)和无符号长整型(unsigned long)三种。
在16位编译器中:
一般一个int型变量占用2字节;
long型(4字节)≥int型(2字节)≥short型(2字节)。
在32位编译器中:
一个int型变量占用4字节;
long型变量占用4字节;
short型变量占用2字节。
实型变量
实型变量分为两种:
1、单精度实型,类型关键字为float,一般占用内存4字节,保留6-7位有效数字。
2、双精度实型,类型关键字为double,一般占用内存8字节,保留15-16位有 效数字。
例如:
float a; a=123456.789 //实际a的值是 123456.7
double b; b=123456.789 //实际b的值是 123456.789
由于实型变量占用有限的内存单元,因此能够提供的有效位数总是有限的,有效位之外的数字 将被舍去,由此将会产生一些误差。应当避免将一个很大的数和一个很小的数直接相加或相减,否 则将会“丢失”小的数。
字符型变量
字符型变量的类型关键字是char
,存放的是字符的ASCII码值(无符号整数), 占用内存1字节。
需要注意的是,字符串只能是常量,C语言中没有字符串变量,而是用字符数组 存放字符串变量。
变量的定义
C语言规定,任何变量必须先定义后使用。
变量定义语句的一般格式: 数据类型符 变量名1[,变量名2,…]; int a,b,c;
对变量进行定义时,需要注意以下几个方面:
1、变量定义可以存放在函数之外,也可以放在函数体或符合语句中。
2、被定义为整型(包括int、short和long)的变量,若其值为-128~127,则 可以作为字符型变量使用。
3、被定为无符号整型(包括unsigned、unsigned short和unsigned long) 的变量,若其值0~255,也可以作为字符型变量使用。
4、被定义为字符型的变量,可以作为整型(包括int、short和long)变量使用, 其将值为-128~127,也可以作为无符号整型(包括unsigned、unsigned short和unsigned long)变量使用,其值将为0~255。
5、变量定义后,系统自动为其分配连续的内存单元,所占用的内存字节数取决 于变量的数据类型。
变量的初始化
变量的初始化是给变量赋值的一种方式,定义变量的同时给变量赋初值称为变量 的初始化。
变量初始化语句的一般格式: 数据类型符 变量名1=初值1[,变量名2[=初值2],...];
变量的使用:先定义,后使用
变量定义位置:一般放在函数开头 变量初始化:可以在定义时赋初值
extern int d = 3, f = 5; // d 和 f 的声明与初始化
int d = 3, f = 5; // 定义并初始化 d 和 f
byte z = 22; // 定义并初始化 z
char x = 'x'; // 变量 x 的值为 'x'
C 中的变量声明
变量声明向编译器保证变量以指定的类型和名称存在,这样编译器在不需要知道变量完整细节的情况下也能继续进一步的编译。变量声明只在编译时有它的意义,在程序连接时编译器需要实际的变量声明。
变量的声明有两种情况:
1、一种是需要建立存储空间的。例如:int a 在声明的时候就已经建立了存储空间。
2、另一种是不需要建立存储空间的,通过使用extern关键字声明变量名而不定义它。 例如:extern int a 其中变量 a 可以在别的文件中定义的。
除非有extern关键字,否则都是变量的定义。
extern int i; //声明,不是定义
int i; //声明,也是定义
尝试下面的实例,其中,变量在头部就已经被声明,但是定义与初始化在主函数内:
#include <stdio.h>
// 函数外定义变量 x 和 y
int x;
int y;
int addtwonum()
{
// 函数内声明变量 x 和 y 为外部变量
extern int x;
extern int y;
// 给外部变量(全局变量)x 和 y 赋值
x = 1;
y = 2;
return x+y;
}
int main()
{
int result;
// 调用函数 addtwonum
result = addtwonum();
printf("result 为: %d",result);
return 0;
}
如果需要在一个源文件中引用另外一个源文件中定义的变量,我们只需在引用的文件中将变量加上 extern 关键字的声明即可。
addtwonum.c 文件代码:
#include <stdio.h>
/*外部变量声明*/
extern int x ;
extern int y ;
int addtwonum()
{
return x+y;
}
test.c 文件代码:
#include <stdio.h>
/*定义两个全局变量*/
int x=1;
int y=2;
int addtwonum();
int main(void)
{
int result;
result = addtwonum();
printf("result 为: %d\n",result);
return 0;
}
第四节 运算符和表达式
1、运算符分类: 运算符是进行各种运算的符号,例如常用的加、减、乘、除符号,即是运算符。
2. 运算对象
C 语言的运算符必须有运算对象。按照参与运算的运算对象的数目,运算符可分为单目运算符、 双目运算符和三目运算符。其中,若单目运算符位于运算对象的前面,则称为前缀单目运算符;若 单目运算符位于运算对象的后面,则称为后缀单目运算符。双目运算符均位于两个运算对象的中间。 三目运算符在 C 语言中只有一个,即条件运算符,组成该运算符的两个符号夹在三个运算对象之间。 每一运算符都代表对运算对象的某种操作,都具有特定的运算规则。每个运算符的运算对象都 有规定的数据类型,同时运算结果也有确定的数据类型。
3. 优先级
当表达式中出现多个运算符,计算表达式的值会遇到先算哪个,后算哪个的问题,即运算符的 优先级问题,C 语言运算符的优先级从高到低分为 15 个级别。表达式值的计算原则是先进行优先级 高的运算。需要注意的是,括号的优先级高于任何运算符,即用括号括起来的部分先计算,若括号 中嵌套了括号,则内层括号优先于外层括号。
4. 结合性
结合性是指当一个运算对象两侧的运算符具有相同优先级时,该运算对象是先与左边的运算符 结合,还是先与右边的运算符结合。从左至右的结合方向称为左结合;反之,从右至左的结合方向 称为右结合。结合性是 C 语言的独有概念。除单目运算符、赋值运算符和条件运算符是右结合之外其他的运算符都是左结合。
算术运算符
C语言的算术运算符包括+、-、*、/、%、+(取正)和-(取负)。
1、单目运算符+、-的优先级相同,结合性是从右至左。
2、双目运算符*
、/、%的优先级相同,结合性是从左至右。
3、双目运算符+、-的优先级相同,结合性是从左至右。
4、单目算术运算符优先于双目算术运算符。
5、*、/、%优先于+、-。
需要注意的是:
1、除法运算的结果和运算对象的数据类型有关,若两个整数相除,则运算称为整除, 其商为整数,小数部分被舍弃。
2、模运算,要求两侧的运算对象必须为整型,否则出错。
自增、自减运算符
自增和自减运算符分别为++和–,它们都是单目运算符,用于对整型、字符型和指针 型变量的值加1和减1的运算,运算结果仍是原来的数据类型。
1、运算符放在变量之前,即++变量、–变量,则先使变量的值加(或减1),然后再 以变化后的值参与其他运算,即先加(或减)1、后运算。
2、运算符放在变量之后,即变量++、变量–,则变量先参与其他运算,然后再使变量 值加(或减)1,即先运算、后加(或减)1。
使用自增和自减运算符时,需要注意以下几点:
1、自增、自减运算,常用于循环语句中,使循环控制变量加(或减)1,以及指针变 量中,使指针向下(或上)一个地址。
2、自增、自减运算符,不能用于常量和表达式。
3、在表达式中连续使同一个变量进行自增或自减运算时,很容易出错,所以最好避免 这种用法。
自增和自减运算符的优先级如下:
1、自增和自减运算符优先于双目算术运算符;
2、自增、自减运算符和单目算术运算符+、-的优先级相同,结合性是从右至左。
请看下面的实例,了解 C 语言中所有可用的算术运算符:
#include <stdio.h>
int main()
{
int a = 21;
int b = 10;
int c ;
c = a + b;
printf("Line 1 - c 的值是 %d\n", c );
c = a - b;
printf("Line 2 - c 的值是 %d\n", c );
c = a * b;
printf("Line 3 - c 的值是 %d\n", c );
c = a / b;
printf("Line 4 - c 的值是 %d\n", c );
c = a % b;
printf("Line 5 - c 的值是 %d\n", c );
c = a++; // 赋值后再加 1 ,c 为 21,a 为 22
printf("Line 6 - c 的值是 %d\n", c );
c = a--; // 赋值后再减 1 ,c 为 22 ,a 为 21
printf("Line 7 - c 的值是 %d\n", c );
c=--a; //减1后再赋值,c为20,a为20
printf("Line 8 - c 的值是 %d\n" "Line 8 -a的值是%d\n",c,a);
c=++a;
printf("Line 9 -c 的值是 %d\n" "Line 9 -a的值是%d\n",c,a);
}
}
以下实例演示了 a++ 与 ++a 的区别:
#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 );
}
第四节 运算符和表达式(二)
1、算术表达式
表达式中的运算符都是算术运算符的称为算术表达式;
算术表达式由运算对象(常量、变量和函数等)、圆括号和算术运算符组成。
算术表达式的构成规则如下:
1、数值型常量、数值型变量和数值型函数调用是算术表达式。
2、+(算术表达式)、-(算术表达式)是算术表达式。
3、++整型变量、--整型变量、整型变量++、整型变量--是算术表达式。
4、(算术表达式)双目算术运算符(算术表达式)是算术表达式。
5、有限次地使用上述规则获得的表达式都是算术表达式。
二、关系运算符
关系运算符包括>、>=、<、<=、==和!=
六种,它们是双目运算符。
本质上,关系运算符是比较运算,如果关系运算的结果是逻辑值“真”(即关系成立 ),用整数“1”表示;如果关系运算的结果是逻辑值“假”(即关系不成立),用 整数“0”表示。
关系运算符的优先级如下:
1、算术运算符优先于关系运算符。
2、>、>=、<、<=优先于==、!=。
3、>、>=、<、<=的优先级相同,结合性是从左至右。
4、==、!=的优先级相同,结合性是从左至右。 需要注意的是,
C语言中“等于”这一关系运算符是双等号“==”,而不是
单等号“=”(赋值运算符)。
下表显示了 C 语言支持的所有关系运算符。假设变量 A 的值为 10,变量 B 的值为 20,则:
运算符 描述 实例:
请看下面的实例,了解 C 语言中所有可用的关系运算符:
#include <stdio.h>
int main()
{
int a = 21;
int b = 10;
int c ;
if( a == b )
{
printf("Line 1 - a 等于 b\n" );
}
else
{
printf("Line 1 - a 不等于 b\n" );
}
if ( a < b )
{
printf("Line 2 - a 小于 b\n" );
}
else
{
printf("Line 2 - a 不小于 b\n" );
}
if ( a > b )
{
printf("Line 3 - a 大于 b\n" );
}
else
{
printf("Line 3 - a 不大于 b\n" );
}
/* 改变 a 和 b 的值 */
a = 5;
b = 20;
if ( a <= b )
{
printf("Line 4 - a 小于或等于 b\n" );
}
if ( b >= a )
{
printf("Line 5 - b 大于或等于 a\n" );
}
}
关系表达式
关系表达式是用关系运算符将两个表达式连接起来的表达式,例如 a>b、a+b>c-d、(a=3) <=(b=5)、‘a’>=‘b’、(a>b)==(b>c)等都是合法的关系表达式,关系表达式的值是 1 或 0。
关系表达式是用关系运算符将两个表达式连接起来的表达式。 关系表达式的一般形式:表达式 关系运算符 表达式
由于条件、赋值、逗号运算符的优先级低于关系运算符,所以应注意加圆括 号。
三、逻辑运算符和逻辑表达式
1. 逻辑运算符
逻辑运算符包括&&、||和!三种,用于对关系式或逻辑值(真、假)进行运算,运算结果是逻辑 值。
逻辑运算符的说明如下图:
逻辑运算符的优先级如下:
1、!优先于双目算术运算符优先于关系运算符优先于&&优先于||。
2、单目逻辑运算符!和单目算术运算符的优先级相同,结合性均从右至左。
3、双目逻辑运算符“&&”和“||”的结合性是从左至右。
主要注意以下几点:
1、对于逻辑运算结果,“1”表示逻辑真,“0”表示逻辑假; 对于逻辑运算对象“非0”表示逻辑真,“0”表示逻辑假。
2、逻辑与“&&”相当于“同时”,逻辑或“||”相当于“或者”,逻辑非 “!”相当于“否定”。
3、逻辑运算符两侧的运算对象可以是任何类型的数据,如整型、实型、字符 型等。
4、一旦“&&”和“||”能够确定表达式的值,则不再继续运算,即并不是所 有的表达式都被运算。1||(a+b)=1。
下表显示了 C 语言支持的所有关系逻辑运算符。假设变量 A 的值为 1,变量 B 的值为 0,则:
实例
请看下面的实例,了解 C 语言中所有可用的逻辑运算符:
#include <stdio.h>
int main()
{
int a = 5;
int b = 20;
int c ;
if ( a && b )
{
printf("Line 1 - 条件为真\n" );
}
if ( a || b )
{
printf("Line 2 - 条件为真\n" );
}
/* 改变 a 和 b 的值 */
a = 0;
b = 10;
if ( a && b )
{
printf("Line 3 - 条件为真\n" );
}
else
{
printf("Line 3 - 条件为假\n" );
}
if ( !(a && b) )
{
printf("Line 4 - 条件为真\n" );
}
}
逻辑表达式
逻辑表达式是用逻辑运算符将一个或多个表达式连接起来,进行逻辑运算的 式子。
逻辑表达式的构成规则:单目逻辑运算符 表达式
表达式 双目逻辑运算符 表达式
其中,表达式主要是关系表达式,也可以是字符型数据或算术表达式、条件 表达式、赋值表达式、逗号表达式等。由于条件、赋值、逗号运算符的优先 级低于逻辑运算符,所以应注意加圆括号。
四、赋值运算符和赋值表达式
赋值运算符分为基本赋值运算符(又称赋值运算符)、复合赋值运算符(+=、-=、*=、/=、% =、&=、^=、|=、<<=、>>=0)。
本节主要介绍赋值运算符以及复合赋值运算符中的前五种, 其他的复合赋值运算符不作介绍。
1. 基本赋值运算符
基本赋值运算符即赋值运算符“=”,它是双目运算符,赋值运算符的左边必须是变量,右边 是表达式,其作用是将一个表达式的值赋给一个变量。
赋值运算符的优先级:
1、算术运算符优先于关系运算符优先于双目逻辑运算符优先于赋值运算符;
2、赋值运算符的结合性是从右至左。
2、复合赋值运算符
复合赋值运算符是在赋值运算符的前面再加一个双目运算符构成的,它是双目运算符,复合赋 值运算符的左边必须是变量,右边是表达式。复合赋值运算符的一般使用形式如下:
a+=3 a=a+3
x*=y+8 x=x*(y+8)
x%=3 x=x%3
复合赋值运算符的优先级:
1、算术运算符优先于关系运算符优先于双目逻辑运算符优先于复合赋值运算 符。
2、复合赋值运算符和赋值运算符的优先级相同,结合性都是从右至左。
赋值表达式
由赋值运算符或复合赋值运算符将一个变量和一个表达式连接起来的表达式,称为赋值 表达式。
**赋值表达式的构成规则:变量=表达式**
其中,表达式可以是算术表达式、关系表达式、逻辑表达式、条件表达式、赋值表达式 和逗号表达式等。由于逗号运算符的优先级低于赋值运算符,所以应注意加圆括号。
a=b=c=5 //表达式值为5,a,b,c值为5
a=(b=5) // b=5;a=5
a=5+(c=6) //表达式值11,c=6,a=11
a=(b=4)+(c=6) //表达式值10,a=10,b=4,c=6
a=(b=10)/(c=2) //表达式值5,a=5,b=10,c=2
逗号运算符和逗号表达式
逗号运算符又称为顺序求职运算符,它是双目运算符,运算对象是表达式, 常用于for循环语句中。
逗号运算符和逗号表达式
形式:表达式1,表达式2,……表达式n
结合性:从左向右
优先级: 15,级别最低
逗号表达式的值:等于表达式n的值
用途:常用于循环for语句中
列子:
例 a=3*5,a*4 //a=15,表达式值60
#include <stdio.h>
int main()
{
int x,y=7;
float z=4;
x=(y=y+6,y/z);
printf("x=%d\n",x);
}
逗号运算符的优先级:
1、任何运算符优先于逗号运算符,即逗号运算符的优先级最低。
2、逗号运算符的结合性是从左至右。
需要注意的是,并不是任何地方出现的逗号都是逗号运算符。很多情况下, 逗号仅用作分隔符。
用逗号运算符把两个或多个表达式连接起来构成逗号表达式,构成规则: 表达式1,表达式2
其中,表达式可以是算术表达式、关系表达式、逻辑表达式、条件表达式、 赋值表达式和逗号表达式等。
条件运算符和条件表达式
条件运算符是C语言中唯一的一个三目运算符,它是由?和:组合成的,其三 个运算对象均为表达式,其中第一个运算对象可以是任何类型的表达式,通常理解为逻辑表达式。
条件运算符的一般使用形式:
表达式1?表达式2:表达式3
条件运算符的执行过程是先表达式1,若非0,则条件表达式的值是表达式2的 值;若为0,则条件表达式的值是表达式3的值。
条件运算符的优先级:
1、其他运算符优先于条件运算符优先于赋值和复合赋值运算符优先于逗号运 算符。
2、条件运算符的结合性是从右至左。
设 int i=1,j=1,k=2,m=0;
则条件表达式 i==j?(k=3):(m=-3)运算后的值是 3,
变量 1、j 和 m 的值不变,变量 k 的值是 3。
/*等价于(i==j)?(k=3):(m=-3),需要注意的是由于条件运算
符的优先级高于赋值运算符,所以(k=3) 和(m=-3)的括号不可
少*/
位运算符和位运算表达式
为了节省内存空间,系统中常将多个标志状态简单地组合在一起,存储到一个字节(或字)中。 C 语言提供了将标志状态从标志字节中分离出来的位运算功能。位运算是按二进制位进行的运算, 运算对象只能是整型(包括字符型)数据,运算结果仍为整型。
位运算符分为位逻辑运算符和位移位运算符
位逻辑运算符
位逻辑运算符将数据中的每个二进制位上的“0”或“1”作为逻辑值,按位 进行逻辑运算。位逻辑运算符分为按位非、按位与、按位或和按位异或(又 称按位加)四种,其中按位非是单目运算符,其余三种都是双目运算符。
3&9=00000001 3|9=00001011 3^9=00001010
1、运算对象只能是**整型或字符型数据
**。除按位非为单目运算符外,其余均为 双目运算符。
2、参与位逻辑运算时,运算对象以二进制形式进行相应的按位运算。 位逻辑运算符的优先级;
1、~优先于双目算术运算符优先于关系运算符优先于&优先于^优先于|优先于 双目逻辑运算符。
2、~与单目逻辑运算符、自增、自减、单目算术运算符、长度运算符的优先 级相同,结合性是从右至左。
位移位运算符
位移位运算符是将数据作为二进制数,进行向左或向右移动若干位的运算, 分为左移和右移两种,均为双目运算符,其中第一个运算对象的移位对象, 第二个运算对象是移动的二进制位数。
1、运算对象只能是整型或字符型数据。
2、参与位移位运算时,运算对象以二进制形式进行相应的按位运算。
位移位运算符的优先级:
1、算术运算符 优先于位移位运算符优先于关系运算符。
2、位移位运算符的优先级相同,结合性是从左至右。
unsigned int b=248; b=b>>2 运算后的值是62
列1:
int x=4,y=2; 表达式(x>>y)+(x<<y)的值是 17
手动算一下:
代码执行:
#include <stdio.h>
int main(void)
{
int a;
int x=4,y=2;
a=(x>>y)+(x<<y);
printf("%d\n",a);
return 0;
}
运算结果:
长度运算符
长度运算符是单目运算符,其运算对象可以是任何数据类型符或变量。
长度运算符的使用形式:
sizeof(数据类型符)
或sizeof(变量)
长度运算符的优先级:
1、与单目算术运算符、单目逻辑运算符、自增和自减运算符的优先级相同。
2、上述优先级相同的运算符的结合性都是从右至左。
sizeof(int) 4 sizeof(float) 4 sizeof(double) 8
第五节 数据类型转换
自动类型转换:
参与运算的各个数据都转换成数据较长的数据类型,然后计算,结果的类型 就是数据长度较长的数据类型。本质上是较低类型的转换,即
“就高不就低” 或“就长不就短”的原则。
赋值类型转换
先将运算结果的数据类型自动转换为左边变量的数据类型,然后再赋予该变 量。本质上是“就左不就右”的转换原则。
例:设int a=1;float b=2.1;char c=’a’;
则表达式a=b+c的计算过程是先计算b+c,按照“就高不就低”的规则,将 c转换为实型(变量c的值是97,转化为97.0),计算结果是实型,即99.1, 由于变量a是整型,按照“就左不就右”的规则,所以将实型自动转换为整型 赋予变量a,即99赋值给变量a。
强制类型转换
除了自动类型转换和赋值类型转换外,C语言也允许强制类型转换。 数据类型强制转换的一般格式:
(数据类型符)(表达式)
C语言首先按照自动类型转换原则计算表达式的值,然后将其转换为指定的数 据类型。需要注意的是,若表达式仅仅是单个常量或变量时,外面的一对圆 括号可以省略;若是含有运算符的表达式,则必须用一对圆括号括起来。
例:
#include <stdio.h>
main()
{
float x;
int i;
x=3.6;
i=(int)x;
printf("x=%f,i=%d\n",x,i);
}
进行数据类型转换时,需要注意以下几点:
1、强制类型转换获得的是一个所需类型的中间量,原来表达式的类型并不发生变化。
2、表达式计算过程中,参与运算的常量或变量的类型自动转换是临时的,它仅产生 一个临时的、类型不同的数据参与运算,常量或变量的原类型和值均不改变。
3、运算结果赋予变量的类型转换过程中,无论是自动变量的还是强制的,当数据长 度较长的结果存入数据长度较短的变量时,将截去超出的部分,有可能造成错误。
4、数据类型转换将占用系统时间,过多的转换将降低程序的运行效率,所以除了必 要的数据类型转换外,应尽量选择好数据类型,避免不必要的转换。
喜欢网络安全与编程的兄弟可以关注下我的公众号
-------------------------------------------
个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!知识源于分享!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!