C_基础_第二章数据类型、运算符、表达式
第二章数据类型、运算符、表达式
一.数据类型
基本类型:是C语言数据类型的基本型,其值不可再分解为其他类型。构造类型:一种由单种或多种数据类型构造而成的数据类型。 数组 结构 共用体 枚举类型
指针类型:一种特殊的数据类型,其值为某个量的内存地址。
空类型:一种无返回值函数的数据类型。 void

1、数值类型
计算短整型的数值范围是多少?
最大值为 : 0111 1111 1111 1111
先加1 0111 1111 1111 1111 + 1 =1000 0000 0000 0000=pow(2,15)=32768
在减1 最大值=32768-1=32767
最小的值是多少呢?
最小值 1000 0000 0000 0000
先求 1000 0000 0000 0001
先减去1 (减1) 1000 0000 0000 0000
然后取反 ,得到源码 (取反) 1111 1111 1111 1111 读出:-32767
最小值 = - 32768 = 1000 0000 0000 0000
那么无符号的短整型的数据范围是啥呢?
无符号的意思是所有二进制位都应该看成是数值位。
最大值应该是: 1111 1111 1111 1111
人为加1得到 1 0000 0000 0000 0000 = pow(2,16)=65536
然后减去1, 65535
最小值应该是: 0000 0000 0000 0000 =0.
浮点类型: float 4个字节 数值范围 10^38~10^-38之间 %f
double 8个字节 10^308~10^-308之间 %lf
字符类型 char 1个字节 c标准中字符一共有128个 %c / %d
char 1个字节 -128 ~127之间。
最大值 = 0111 1111 = pow(2,7)= 127.
最小值 = 1000 0000 = -128
2.构造类型
在实际应用中,对于复杂问题的解决,C语言还提供了新的数据类型,这些数据类型的元素或成员的数据类型仍然是基本数据类型。
C语言中构造类型共有四种:数组、结构体、共用体(联合体)、枚举。
3.指针类型
C语言里,变量存放在内存中,而内存其实就是一组有序字节组成的数组,每个字节有唯一的内存地址。CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位。这里,数据对象是指存储在内存中的一个指定数据类型的数值或字符串,它们都有一个自己的地址,而指针便是保存这个地址的变量。也就是说:指针是一种保存变量地址的变量。
4.空类型
一类函数调用后并不需要向调用者返回函数值, 这种函数可以定义为“空类型”。其类型说明符为void,不需要向调用者返回函数值 。
void的语义有多种: 1、作为参数表示无参数 2、作为返回值代表无返回值 3、修饰指针变量代表未知类型的指针
二 常量、变量
-常量是固定值,在程序执行期间不会改变。这些固定的值,又叫做字面量。(如果修改常量值(1)程序编译时会发现 报错(2程序崩溃))
1.整形常量
整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制。
常量加前缀:代表不同的进制表现
常量加后缀:代表常量的类型
不加后缀 默认为int类型的常量 L 表示常量为long类型 U 表示常量为无符号的int UL 无符号的long类型(无符号 unsigned 代表没有负数 只有正)
后缀 不区分大小写
%u 以有符号类型输出;
2 浮点型常量
浮点常量由整数部分、小数点、小数部分和指数部分组成(十进制),可以使用小数形式或者指数形式(科学计数法)来表示浮点常量。 当使用小数形式表示时,必须包含整数部分、小数部分,或同时包含两者。当使用指数形式表示时,字母E/e前必须有数字, 而E后面的阶码必须为整数。
两种表现形式
(1)指数(科学计数法)
(2)十进制小数形式
如果要写一个合法的科学计数法表示的浮点数,必须满足两条
(1)、e前面必须有数字。
(2)、e后面必须有整型数。
例如:1234.56 数学中可以写成 :1.23456*10^3,C语言中:1.3456e+003
输出时 默认保留六位小数 并且 四舍五入
输出小数时 % .n f 就代表保留n个小数输出
3,字符常量:
语法:char ' x ' ; 字符常量是括在单引号中,存储在 char 类型的简单变量中。
注意:(1)字符常量可以是一个普通的字符(例如 'x')、一个转义序列(例如 '\t'),或一个通用的字符(例如 '\u02C0’)。
(2)在内存中,字符常量以ASCII码存储,一个字符占一个字节。
` (3)由于字符常量是按整数存储的,可以像整数一样在程序中参与相关的运算。、
数据类型不同的平台可能占用内存大小不一样(分配的空间)
sizeof :测字节运算符 单位是 字节 bytes, sizeof() 括号中 可以跟变量名 类型 常量
例如:
#include <stdio.h> void main() { printf("%d\n",sizeof(double)); }
转义字符
在 C 中,有一些特定的字符,当它们前面有反斜杠时,它们就具有特殊的含义,被用来表示如换行符(\n)或制表符(\t)等。。
4,字符串常量
字符串常量: 用 “” 包括的字符序列叫字符串
编码:在ASCII中 一个字符占一个字节,中文字符 属于 utf-8/Unicode/gbk 一个中文字符占两个字节
字符串长度:从首地址开始到\0之间字符的个数
字符串分配的空间:用sizeof可测
系统自动在每个字符串的末尾加上一个空字符NULL,即’\0’ 作为字符串的结束。’\0’是一个ASCII码为0的字符
字符串中的字符分为两类:
普通字符
特殊字符 第一类,以‘%’开头的,表示格式化输出后面的值。 %格式控制字符 d hd f e c
第二类,以‘\’开头的,表示转意,例如\n表示换行。\转义字符 \n \t \0 \a \b \101
第三类,‘%%’表示输出一个%
5.自定义常量
- 使用 #define 预处理器: #define 可以在程序中定义一个常量,它在编译时会被替换为其对应的值。
说明: 预处理命令#define也称为宏定义, 一个#define命令只能定义一个符号常量, 用一行书写, 不用分号结尾。
符号常量名习惯用大写字母表示
该命令通常放在文件头 在程序中, 符号常量不允许重新赋值。
-
-
- 例如:
-
#include <stdio.h> #define WELCOME "欢迎来蚂蚁软件学习" void main() { printf(WELCOME); } //1、用一个符号,来表示一堆代码就叫做宏。(符号常量就是宏的一个特例。 //是编译时候,替换的,还是运行的时候替换的? 答案:编译时。更精确的说法, //应该是预编译阶段完成的。预编译有三个内容, //1,#include //2,#define 宏定义 //3#iffine 条件编译,解决重复引用的问题,需要用到条件编译。
-
带参数的宏。
-
-
-
#define GET_VALUE(r) (3* (r) * (r)) //写带参数宏的时候,一定要用括号将每个参数括起来。 int fun(int r) { return 3 * r * r; } void main() { int a = 0; printf("%d\n",GET_VALUE(3+2)); } // 预编译时,将 printf("%d\n",GET_VALUE(3+2))替换成printf("%d\n",(3*(3+2)*(3+2))) 函数调用,printf("%d\n",fun(3+2));//当函数调用时,是实参先进行运算,形参开辟空间,接收实参计算后的值。
-
-
函数和带参数宏的区别:
1) 从程序的执行来看
函数调用会带来额外的开销,它需要开辟一片栈空间,记录返回地址,将形参压栈,从函数返回还要释放栈。这种开销不仅会降低代码效率,而且代码量也会大大增加。而宏定义只在编译前进行,不分配内存,不占运行时间,只占编译时间,因此在代码规模和速度方面都比函数更胜一筹。
2) 从参数的类型来看
函数的参数必须声明为一种特定的数据类型,如果参数的类型不同,就需要使用不同的函数来解决,即使这些函数执行的任务是相同的。而宏定义则不存在着类型问题,因此它的参数也是无类型的。也就是说,在宏定义中,只要参数的操作是合法的,它可以用于任何参数类型。
3) 从参数的副作用来看
毋庸置疑,在宏定义中,在对宏参数传入自增(或者自减)之类的表达式时很容易引起副作用,尽管前面也给出了一些解决方案,但还是不能够完全杜绝这种情况的发生。与此同时,在进行宏替换时,如果不使用括号完备地保护各个宏参数,那么很可能还会产生意想不到的结果。除此之外,宏还缺少必要的类型检查。而函数却从根本上避免了这些情况的产生。
4) 从代码的长度来看
在每次使用宏时,一份宏定义代码的副本都会插入程序中。除非宏非常短,否则使用宏会大幅度地增加程序的长度。而函数代码则只会出现在一个地方,以后每次调用这个函数时,调用的都是那个地方的同一份代码。
-
onst 关键字
使用 const 前缀声明指定类型的常量,如下所示:
const 数据类型 常量名 = 常量值;
下面的代码定义了一个名为MAX_VALUE的常量:
const int MAX_VALUE = 100;
在程序中使用该常量时,其值将始终为100,并且不能被修改。
- 字符串常量和字符常量的主要区别:
- 字符常量由单引号括起来, 字符串常量由双引号括起来。
-
字符常量只能是单个字符,字符串常量可以含有多个字符。
-
字符常量占一个字节, 字符串常量占的字节数等于字符个数加1。
三 变量
变量的定义
变量的初始化
变量的不初始化
变量的声明
-
- 一种是需要建立存储空间的。例如:int a 在声明的时候就已经建立了存储空间。
- 另一种是不需要建立存储空间的,通过使用extern关键字声明变量名而不定义它。 例如:extern int a 其中变量 a 可以在别的文件中定义的。
除非有 extern 关键字,否则都是变量的定义。
extern int i; //声明,不是定义
int i; //声明,也是定义
-
C 中的左值(Lvalues)和右值(Rvalues)
c中有两种类型的表达式:
- 左值(lvalue):指向内存位置的表达式被称为左值(lvalue)表达式。左值可以出现在赋值号的左边或右边。
- 右值(rvalue):术语右值(rvalue)指的是存储在内存中某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现在赋值号的左边。
变量是左值,因此可以出现在赋值号的左边。数值型的字面值是右值,因此不能被赋值,不能出现在赋值号的左边。下面是一个有效的语句:
int g = 20;
但是下面这个就不是一个有效的语句,会生成编译时错误:
10 = 20;
四 运算符和表达式
1.基础概念
运算符(operator)是可以对数据进行相应操作的符号。
操作数(operand)是程序操纵的数据实体,该数据可以是数值、逻辑值或其他类型。该操作数既可以是常量也可以为变量。
一元运算符、二元运算符和多元运算符 根据运算符可操作的操作数的个数,可把运算符分为一元运算符、二元运算符和多元运算符(一般三元)。
优先级:C语言中,运算符的运算优先级共分为15级。1级最高,15级最低。 在表达式中,优先级较高的先于优先级较低的进行运算。而在一个运算量两侧的运算符
优先级相同时,则按运算符的结合性所规定的结合方向处理。
结合性:C语言中各运算符的结合性分为两种,即左结合性(自左至右)和右结合性(自右至左)。
优先级相同时看结合性,C语言结合性较为复杂,一般建议使用()来显式表达计算结合性。
规律记住:
单目运算都是右结合。
双目运算都是左结合。
啥叫左结合?从左边向右边计算就叫左结合
注!优先级相同时看结合性,因C的结合性较为复杂,一般用()来凸显结合性,但当出现 &&(逻辑与)、||(逻辑或)(称伪0级)这两种运算符时,优先级失效!&&和||具有“短路”特性。
2 算术运算
算术运算符号。作用:做算术四则运算的
+ 需要记住由低类型向高类型转换。
- 需要记住由低类型向高类型转换。
* 需要记住由低类型向高类型转换。
/ (1)两个整数相除,必得整数,此为地板除。(2)分子或者分母有一个是浮点数,其结果就是通常意义的除法。
% ( 1 ) 用于计算两个数相处后得到的余数。
(2)参与运算的量必须是整型量,其结果也是整型量。 5%3= 2 5.2%3(错了,不能算非整型数)
(3)某个数和N取余,其结果的范围是[0,N-1]
i++/i-- (1)自增 自减运算符 仅代表 i的值自增1 或 自减1
(2)为什么要有i++ 是为了延迟自增 很多需求下 我们需要在循环中 使用i当前的值 遇到;i再自增
(3)所以说i++ 使用会有很多误导 虽然可以简化操作 不理解用法时 尽量别用

不同数据类型间的转换与运算
(1)实型数据赋给整型变量时,只取整数部分
(2)整型数据赋给实型变量时,以浮点形式取值
(3)字符型数据赋给整型变量时, 整型变量的高位补的数与char的最高位相同, 低八位为字符的ASCII码值。
(4)整型数据赋给字符型时,只把低8位赋给字符变量
在C程序中, 当不同类型的量进行运算时, 要转换成同一种类型然后再进行运算。
例: 10+‘a’+1.5-8765.1234*‘b’
自动转换: 数据类型自动由低级向高级转换。
低类型数据与高类型数据参与运算得到的结果是高类型,由编译系统自动完成从低到高依次 字符 整型 实型(同类型看数据范围,无符号类型高于有符号类型)
强制转换: 将表达式的运算结果强制转换成指定的数据类型。
强制转换得到的是中间结果类型,原变量类型不变,数据类型说明符和表达式都必须加括号(单个变量除外)
格式:(数据类型)(表达式)2级
强制类型转换并不会改变原数据 它只是一个中间类型的运算结果

3.关系运算(比较运算)

注意 : (1)一个等号=,是赋值运算符。
(2)二个等号== ,是比较是否相等运算符号
(3)用比较运算符 结果是一个逻辑值 0或1
4.逻辑运算符

逻辑与 和 逻辑或 的短路情况
当遇到这俩个运算符时 不能根据优先级去计算了 伪0级
练习:请将一个整数高八位取出来
-
-
#include <stdio.h> void main() { int a = 0; int b = 0; scanf("%x",&a);//按16进制读入 b = (a&0xff000000)>>24; printf("%x",b);//%x hexadecimal,这个是按16进制输出的意思。 } 说明 0000 0000 0000 0000 0000 0000 0001 0001 & 1111 1111 0000 0000 0000 0000 0000 0000 -———————————————————————— aaaa aaaa 0000 0000 0000 0000 0000 0000
-
结论:当你想从一个整型数中得到一些二进制位的数值,应该用位与运算。
4.条件运算符
条件运算符: 唯一的一个三目(三元)运算符,13级 加括号是右结合,不加括号是左结合
语法: 条件(逻辑值)?真:假 条件为真执行左边的表达式 为假执行右边的表达式
结果:条件运算符的返回结果即为执行的表达式的结果
-
-
#include<stdio.h> int main() { int a = 3; int b = 5; int max = 0; max = a>b?a:b; printf("%d",max); } 在条件表达式中, 各表达式的类型可以不同, 此时,条件表达式值的类型为表达式2和表达式3中较高的类型
-
5.赋值运算符

赋值运算符:(右侧的计算值,赋值给左侧的变量)
a=a+3; 等价于 a+=3
a=a-3 a-=3
在实际工作中 不建议这样去写 会降低可读性
赋值运算的类型转换规则(4点):
1.实型数据赋给整型变量时,只取整数部分;
2.整型数据赋给实型变量时,以浮点数形式取值;
3.字符型数据赋给整型变量时,整型变量高位补得数与字符的最高位相同,低八位是字符的ASCII码值;
4.整型数据赋给字符型变量时,只把低八位赋给字符变量。
6.位运算符

位与 都为1才为1
位或 有1为1
异或 不同为1 相同为0,不同为1:作用是两个整数二进位中哪些位不同
-
-
void main() { short int a = 31; short int b = 15; short int c = a^b; printf("%hd",c); } 分析; a: 0000 0000 0001 1111 b: 0000 0000 0000 1111 ^ ---------------------------------------- 000;0 0000 0001 0000 所以结果就是16 自反 所有二进制位取反 包括符号位 取相反数-1 单目 #include <stdio.h> void main() { short int a = 5; a = ~a; printf("%hu",a);%hd这是按短整型有符号输出A } 说明: 5 = 0000 0000 0000 0101 ~5 = 1111 1111 1111 1010 (因为第一位是1,所以必须推到原码才可以正确的读出。) 补码 = 源码 -> 取反->+1 1111 1111 1111 1010 - 0000 0000 0000 0001 _______________________ 1111 1111 1111 1001 取反 1000 0000 0000 0110 = - 6
-
左移 如 左移n 就相当于 原数*2的n次方
右移 右移n 就相当于 原数地板除2的n次方
7、大小端:
对于一个基本整型,是4个字节。在内存中如何存放呢?
大端: 高字节放到低地址上,低字节就放到高地址。
因为我们经常表示内存地址,左侧是低地址,右侧是高地址。
12 34 56 78 对应二进制:00010010001101000101011001111000(b)
小端:低字节放到低地址上,高字节就放到高地址。
78 56 34 12 对应二进制:01111000010101100011010000010010
-
例题:有个整型数字,本来是按小端存放的,但错误的认为是大端存放的,读出来这个数字为320,请问,这个数应该是什么?写个程序计算出来。 分析:320 的16进制的写法是 0x00000140 按小端存放: 00 00 01 40 四个字节是这样存放的。 按大端存放: 0x40010000 #include <stdio.h> void main() { int a = 320; int b = a&0x000000ff;//这个是低8位。 int c = (a&0x0000ff00)>>8;//右数的第二个8位。 int d = (a&0x00ff0000)>>16;//右边的第三个字节取出来了。 int e = (a&0xff000000)>>24;//左边的第一个字节取出来了。 printf("%d",e + (d<<8) + (c<<16) + (b<<24)); }
7.逗号运算符
逗号运算符是二元运算符 表达式1 , 表达式2
逗号运算符确保操作数被顺序地处理:先计算左边的操作数,再计算右边的操作数。右操作数的类型和值作为整个表达式的结果。
逗号运算符的优先级是所有运算符中最低的。
注! 重点*****
1.整型数据赋给字符型变量时,只把低八位赋给字符变量。
2.在计算机中,不同类型的数据是无法计算的,必须要转换成相同类型的才能参与运算;
3.把一个浮点数按%d输出时,会输出一个乱值;
4.把一个整型数按%f输出时,会输出零值。
将整形值赋给实型变量时, 如: float a = 5; 5.000000
将实型值赋给整型变量是, int a = 3.5 3 (只取整数部分)
将字符值赋给整型变量时 int a = ‘A’ 65(取ascii值)
将整型值赋给字符变量时 char ch = 300; 只取低八位 300-256 ==44

浙公网安备 33010602011771号