定制网站开发介绍图,移动网站适配,北京融安特智能科技营销型网站,做海外网站交税吗第02章_变量与进制
讲师#xff1a;尚硅谷-宋红康#xff08;江湖人称#xff1a;康师傅#xff09;
官网#xff1a;http://www.atguigu.com 本章专题脉络 1、关键字(keyword)
定义#xff1a;被C语言赋予了特殊含义#xff0c;用做专门用途的字符串#xff08;或单…第02章_变量与进制
讲师尚硅谷-宋红康江湖人称康师傅
官网http://www.atguigu.com 本章专题脉络 1、关键字(keyword)
定义被C语言赋予了特殊含义用做专门用途的字符串或单词。
特点全部关键字都是小写字母。
举例HelloWorld案例中出现的关键字有 int、return等这些单词已经被C语言定义好了。
传统的C语言ANSI C有32个关键字。如下
类型具体关键字控制语句关键字12 个break, case, continue, default, do, else, for, goto, if, return, switch, while数据类型关键字12 个char, enum, double, long, float, int, short, signed, struct, unsigned, union, void存储类型关键字4 个auto, extern, register, static其他关键字4 个const, sizeof, typedef, volatile
后续1999年C99标准增加了5个关键字inline、restrict、_Bool、_Complex和_Imaginary。
2011年C11标准又增加了7个关键字_Alignas、_Alignof、_Atomic、_Static_assert、_Noreturn、_Thread_local和_Generic。 说明 1、ANSI C、C99和C11它们之间差别并不大在大多数情况下它们都是和谐共处的。 2、不需要死记硬背学到哪里记到哪里即可。 2、标识符(Identifier)
C语言中变量、函数、数组名、结构体等要素命名时使用的字符序列称为标识符。
技巧凡是自己可以起名字的地方都叫标识符。
标识符的命名规则必须遵守的硬性规定
只能由26个英文字母大小写0-9 或 _ 组成数字不可以开头不可以是关键字但可以包含关键字C99和C11允许使用更长的标识符名但是编译器只识别前63个字符。(会忽略超出的字符)不允许有空格。严格区分大小写字母。比如Hello、hello是不同的标识符。
标识符的命名建议建议遵守的软性要求 在起名字时为了提高阅读性要尽量有意义“见名知意”。如sumnamemaxyeartotal 等。 不要出现仅靠大小写区分不同的标识符。如name、Name 容易混淆 尽量避免名字中出现数字编号如value1、value2等除非逻辑上需要编号。 习惯上所有宏定义、枚举常数、常量(只读变量)全用大写字母命名用下划线分隔单词。 比如 const double TAX_RATE 0.08; //TAX_RATE 只读变量 系统内部使用了一些下划线开头的标识符比如两个下划线开头的变量名、一个下划线 大写英文字母开头的变量名。比如C99 标准添加的类型 _Bool。为防止冲突建议用户尽量避免使用下划线开头的标识符。 下划线通常用于连接一个比较长的变量名。如max_classes_per_student。 变量名、函数名多单词组成时第一个单词首字母小写第二个单词开始每个单词首字母大写xxxYyyZzz (驼峰法小驼峰)。比如short stuAge 20; tankShotGame。
举例合法的标识符
a、BOOK1、_sun、MAX_SIZE、Mouse、student23、Football、FOOTBALL、max、_add、num_1、sum_of_numbers举例非法的标识符
$zj、3sum、ab#cd、23student、Foot-baii、s.com、bc、j**p、book-1、tax rate、dont【武汉科技大学2019研】 以下均是合法变量名的是 。 A#name total Bnode value_max C_var long Dstucode ab 【答案】B 【解析】C语言中变量名只能包含数字字母和下划线且只能以字母和下划线开始。A项含非法字符#错误C中long为关键字变量不能以关键字命名D中含非法字符和。 【四川大学2017研】以下不合法的用户标识符是 。 AJ2_KEY BDouble C4d D_8_ 【答案】C 【解析】标识符只能包含数字字母下划线且不能以数字开头选项C错误。 练习 下列定义变量的语句中错误的是 。 Adouble int_ Bfloat US$ Cchar For Dint _int 【答案】B【解析】标识符由字母、数字、下划线组成。$是非法字符不能出现在标识符中。答案选择B选项。 3、变量(variable)
3.1 为什么需要变量 一花一世界如果把一个程序看做一个世界或一个社会的话那么变量就是程序世界的花花草草、万事万物。即变量是程序中不可或缺的组成单位最基本的存储单元。 3.2 初识变量 变量的概念 内存中的一个存储区域该区域的数据可以在同一类型范围内不断变化。 通过变量名可以访问这块内存区域获取里面存储的值。 变量的构成包含三个要素数据类型、变量名、存储的值 C语言中变量声明的格式数据类型 变量名 变量值 变量的作用用于在内存中保存数据。 使用变量注意 C语言中每个变量必须先声明后使用。不同的数据类型占用的空间大小不一样。一旦声明变量的类型就不能在运行时修改。
3.3 变量的声明与赋值
步骤1变量的声明
格式
数据类型 变量名; //声明变量的语句必须以分号结尾举例1
int width;举例2
int width,height;// 等同于
int width;
int height;步骤2变量的赋值
变量声明时就为它分配内存空间但是不会清除内存里面原来的值。这导致声明变量以后变量会是一个随机的值。所以变量一定要赋值以后才能使用。
int age; //变量的声明
age 18; //变量的赋值变量的声明和赋值也可以写在一行。
int age 18;多个相同类型变量的赋值可以写在同一行。
int a 1, b 2;int a, b;
a 1;
b (a 2 * a);int a, b, c, x, y;
a b c x y 10; //连续赋值注意声明变量以后不用忘记初始化赋值定义变量时编译器并不一定清空了这块内存它的值可能是无效的数据运行程序会异常退出。 3.4 变量的作用域(scope) 变量的作用域其定义所在的一对{ }内。 变量只有在其作用域内才有效。出了作用域变量不可以再被调用。 同一个作用域内不能定义重名的变量。 C 语言的变量作用域主要有两种文件作用域file scope和块作用域block scope。
文件作用域file scope指的是在源码文件顶层声明的变量从声明的位置到文件结束都有效。
int x 1;
int main() {printf(%d\n, x);return 0;
}块作用域block scope指的是由大括号 {} 组成的代码块它形成一个单独的作用域。凡是在块作用域里面声明的变量只在当前代码块有效代码块外部不可见。
int main() {int m 10;if (m 10) {int n 20;printf(%d %d\n, m, n); // 10 20}printf(%d\n, m); // 10printf(%d\n, n); // 超出作用域报错return 0;
}最常见的块作用域就是函数函数内部声明的变量对于函数外部是不可见的。 for 循环也是一个块作用域循环变量只对循环体内部可见外部是不可见的。
for (int i 0; i 10; i){printf(%d\n, i);
}
printf(%d\n, i); // 超出作用域报错3.5 变量按类型的分类
变量可以按数据类型来分也可以按声明的位置来分全局变量、局部变量。本节主讲变量的不同类型。
C 语言中的变量按照数据类型分为 注意1这里列举的是C语言的常用类型后续C语言版本还有新增的类型。 注意2空类型void 表示空类型无类型。通常应用于函数的返回值类型、函数的参数、指针类型。 注意3在C语言中没有字符串类型使用字符数组表示字符串。 4、基本数据类型
4.1 整数类型
4.1.1 类型说明 C语言规定了如下的几类整型短整型(short)、整型(int)、长整型(long)、更长的整型(long long) 每种类型都可以被 signed 和unsigned 修饰。其中 使用 signed 修饰表示该类型的变量是带符号位的有正负号可以表示负值。默认是signed。使用 unsigned 修饰表示该类型的变量是不带符号位的没有正负号只能表示零和正整数。 bit(位)计算机中的最小存储单位。 byte(字节)计算机中基本存储单元。 1byte 8bit
类型修饰符占用空间取值范围short [int]signed2个字节(16位)-32768 ~ 32767 (- 2 15 2^{15} 215 ~ 2 15 2^{15} 215-1)short [int]unsigned2个字节(16位)0 ~ 65535 (0 ~ 2 16 2^{16} 216-1)intsigned通常4个字节-2147483648 ~ 2147483647 (- 2 31 2^{31} 231 ~ 2 31 2^{31} 231-1)intunsigned通常4个字节0 ~ 4294967295 (0 ~ 2 32 2^{32} 232-1)long [int]signed4个或8个字节4字节时-2147483648 ~ 2147483647 (- 2 31 2^{31} 231 ~ 2 31 2^{31} 231-1)long [int]unsigned4个或8个字节4字节时-0 ~ 4294967295 (0 ~ 2 32 2^{32} 232-1)
long long int是C99新增的
类型修饰符占用空间取值范围long long [int]signed8个字节(64位)-9223372036854775808~ 9223372036854775807(- 2 63 2^{63} 263 ~ 2 63 2^{63} 263-1)long long [int]unsigned8个字节(64位)0 ~ 18446744073709551615(0 ~ 2 64 2^{64} 264-1) 说明1不同计算机的 int 类型的大小是不一样的。比较常见的是使用4个字节32位存储一个 int 类型的值具体情况如下 类型16位编译器32位编译器64位编译器short int2字节2字节2字节int2字节4字节4字节unsigned int2字节4字节4字节long4字节4字节8字节unsigned long4字节4字节8字节long long8字节8字节8字节 说明2C标准虽然没有具体规定各种类型数据所占用存储单元的长度但几条铁定的原则ANSI/ISO制订的 ① sizeof(short int) ≤ sizeof(int) ≤ sizeof(long int) ≤ sizeof(long long)具体由各编译系统自行决定的。其中sizeof是测量类型或变量长度的运算符。 ② short int至少应为2字节long int至少应为4字节。 这样约定的好处就是使得C语言可以长久使用。现在的主流CPU是64位可以预测不久的将来会推出128位甚至256位的CPU但是在C语言刚刚出现的时候CPU还是以8位和16位为主。如果那时候就将整型定死为8位或16位那么现在我们肯定不会再学习C语言了。 说明3 最常用的整型类型为int类型。 整数型常量默认为int类型。 4.1.2 举例
举例1对于 int 类型默认是带有正负号的。即 int 等同于 signed int 。一般情况下关键字signed省略不写。
signed int m; //声明了一个带符号的整数变量 m
// 等同于
int m; //声明了一个带符号的整数变量 m举例2int 类型也可以不带正负号只表示非负整数。这时就必须使用关键字 unsigned 声明变量。表数范围为0~4294967295
unsigned int a; //声明了一个不带符号的整数变量a表数范围为0~4294967295unsigned int 里面的 int 可以省略所以上面的变量声明也可以写成这样
unsigned a;举例3
int 类型使用4个字节表示一个整数对于小整数这样做很浪费空间。另一方面某些场合需要更大的整数4个字节还不够。此时可以使用short int 简写为 short 、long int 简写为 long 、long long int 简写为 long long
signed short int a;
signed long int b;
signed long long int c;默认情况下 short 、 long 、 long long 都是带符号的signed即 signed 关键字可以省略。代码简写为
short a;
long b;
long long c;它们也可以声明为不带符号unsigned使得能够表示的最大值扩大一倍。
unsigned short a; //无符号短整型表数范围0~65535
unsigned long b; //无符号长整型表数范围0~4294967295
unsigned long long c; //无符号长整型表数范围0~184467440737095516154.1.3 关于后缀
编译器将一个整数常量指定为 int 类型但是如果希望将其指定为 long 类型需要在该字面量末尾加上后缀 l 或 L 编译器会把这个字面量的类型指定为 long 。
long x 123L; //或者写成 123l如果希望字面量指定为long long类型则后缀以ll或LL结尾。
long long y 123LL;如果希望指定为无符号整数 unsigned int 可以使用后缀 u 或 U 。
unsigned int x 123U;L 和 U 可以结合使用表示 unsigned long 类型。 L 和 U 的大小写和组合顺序无所谓。
u 还可以与其他整数后缀结合放在前面或后面都可以比如 10UL 、 10ULL 和 10LLU 都是合法的。
unsigned long int x 1234UL;
unsigned long long int x 1234ULL;4.1.4 精确宽度类型(了解)
C 语言的整数类型short、int、long在不同计算机上占用的字节宽度可能是不一样的无法提前知道它们到底占用多少个字节。程序员有时控制准确的字节宽度这样的话代码可以有更好的可移植性头文件 stdint.h 创造了一些新的类型别名。
精确宽度类型(exact-width integer type)保证某个整数类型的宽度是确定的。 int8_t 8位有符号整数 int16_t 16位有符号整数 int32_t 32位有符号整数 int64_t 64位有符号整数 uint8_t 8位无符号整数 uint16_t 16位无符号整数 uint32_t 32位无符号整数 uint64_t 64位无符号整数
上面这些都是类型别名编译器会指定它们指向的底层类型。比如某个系统中如果 int 类型为32位 int32_t 就会指向 int 如果 long 类型为32位 int32_t 则会指向 long 。
#include stdio.h
#include stdint.hint main() {int32_t x32 45933945; //变量 x32 声明为 int32_t 类型可以保证是32位的宽度。printf(x32 %d\n, x32);return 0;
}4.1.5 整型的极限值(了解)
有时候需要查看当前系统不同整数类型的最大值和最小值C 语言的头文件 limits.h 提供了相应的常量。比如INT_MIN 代表 signed int 类型的最小值 -2147483648 INT_MAX 代表 signed int 类型的最大值 2147483647。
#include limits.hint main() {printf(%d\n, INT_MIN ); // -2147483648printf(%d\n, INT_MAX ); // 2147483647return 0;
}为了代码的可移植性需要知道某种整数类型的极限值时应该尽量使用这些常量。 SCHAR_MIN SCHAR_MAX signed char 的最小值和最大值。 SHRT_MIN SHRT_MAX short 的最小值和最大值。 INT_MIN INT_MAX int 的最小值和最大值。 LONG_MIN LONG_MAX long 的最小值和最大值。 LLONG_MIN LLONG_MAX long long 的最小值和最大值。 UCHAR_MAX unsigned char 的最大值。 USHRT_MAX unsigned short 的最大值。 UINT_MAX unsigned int 的最大值。 ULONG_MAX unsigned long 的最大值。 ULLONG_MAX unsigned long long 的最大值。
4.2 浮点类型
4.2.1 类型说明
浮点型变量也称为实型变量用来存储小数数值的。因为32位浮点数提供的精度或者数值范围还不够C 语言又提供了另外两种更大的浮点数类型。
在C语言中浮点型变量分为三种单精度浮点型(float)、双精度浮点型(double)、长双精度浮点型(long double)。
类型占用空间取值范围float4个字节 (32位) − 1.4 ∗ 1 0 − 45 -1.4*10^{-45} −1.4∗10−45 ~ − 3.4 ∗ 1 0 38 -3.4*10^{38} −3.4∗1038 1.4 ∗ 1 0 − 45 1.4*10^{-45} 1.4∗10−45 ~ 3.4 ∗ 1 0 38 3.4*10^{38} 3.4∗1038double8个字节 (64位) − 4.9 ∗ 1 0 − 324 -4.9*10^{-324} −4.9∗10−324 ~ − 1.7 ∗ 1 0 308 -1.7*10^{308} −1.7∗10308 4.9 ∗ 1 0 − 324 4.9*10^{-324} 4.9∗10−324 ~ 1.7 ∗ 1 0 308 1.7*10^{308} 1.7∗10308long double12个字节(96位)太大了…
其中
类型16位编译器32位编译器64位编译器float4字节4字节4字节double8字节8字节8字节
C语言的第3种浮点类型是long double以满足比double类型更高的精度要求。不过C只保证long double类型至少与double类型的精度相同。
浮点型变量不能使用signed或unsigned修饰符。
最常用的浮点类型为double 类型因为精度比float高。
浮点型常量默认为 double 类型。
关于后缀
对于浮点数常量编译器默认指定为 double 类型如果希望指定为float类型需要在小数后面添加后缀 f或F如果希望指定为long double类型需要在小数后面添加后缀 l或L。
float x 3.14f;
double x 3.14;
long double x 3.14L;4.2.2 举例
举例1
float f 123.4f; //后面必须加上字母f
double d1 101.1; //后面可以省略字母d举例2
C 语言允许使用科学计数法表示浮点数使用字母 e 来分隔小数部分和指数部分。注意e 的前后不能存在空格。
double x 123.456e3; // 123.456 x 10^3
// 等同于
double x 123.456e3;另外科学计数法的小数部分如果是 0.x 或 x.0 的形式那么 0 可以省略。
0.3E6
// 等同于
.3E63.0E6
// 等同于
3.E6**举例3**可以在常量的末尾加专用字符强制指定常量的类型
float a 3.14159f; //把此3.14159按单精度浮点常量处理
long double a 1.23L; //把此1.23作为long double型处理举例4
有人用温度计测量出用华氏法表示的温度(如64°F今要求把它转换为以摄氏法表示的温度(如17.8℃)。转换的公式为 c 5 9 ( f − 32 ) c \frac{5}{9}(f - 32) c95(f−32)。
其中f 代表华氏温度c 代表摄氏温度。
#include stdio.hint main() {float f, c; //定义f和c分别表示华氏温度、摄氏温度f 64.0; //指定f的值c (5.0 / 9) * (f - 32); //利用公式计算c的值printf(f%f\nc%f\n, f, c); //输出c的值return 0;
}4.2.3 存储规则(了解)
任何有小数点的数值都会被编译器解释为浮点数。所谓“浮点数”就是使用 m * b^e 的形式存储一个数值 m 是小数部分 b 是基数 e 是指数部分。
从十进制的角度 从二进制的角度
根据国际标准IEEE电气和电子工程协会 754任意一个二进制浮点数V可以表示成下面的形式 ( − 1 ) S ∗ M ∗ 2 E (-1)^S * M * 2^E (−1)S∗M∗2E
其中 ( − 1 ) s (-1)^s (−1)s表示符号位当s0V为正数当s1V为负数。 M表示有效数字大于等于1小于2。 2 E 2^E 2E表示指数位。
举例来说
十进制的5.0写成二进制是 101.0 相当于 1.01×2^2 。即按照上面V的格式可以得出s0M1.01E2。
十进制的-5.0写成二进制是 -101.0 相当于 -1.01×2^2 。即s1M1.01E2。
IEEE 754规定
对于32位的浮点数最高的1位是符号位s接着的8位是指数E剩下的23位为有效数字M。 对于64位的浮点数最高的1位是符号位S接着的11位是指数E剩下的52位为有效数字M。 浮点数的存储方式决定了浮点数精度控制在一定范围内。有效数字部分可能丢失造成精度损失。
4.3 字符类型
C语言中使用 char 关键字来表示字符型用于存储一个单一字符。
字符型变量赋值时需要用一对英文半角格式的单引号把字符括起来。
每个字符变量在16位、32位或64位编译器中都是占用 1 个字节(8位)。
表示方式1最常见
char c A; //为一个char类型的变量赋值字符A每个字符对应一个整数由 ASCII 码确定比如 A 对应整数 65 。
只要在字符类型的范围之内整数与字符是可以互换的都可以赋值给字符类型的变量。
表示方式2ASCII 码值
char c 66;
// 等同于
char c B;两个字符类型的变量可以进行数学运算。
char a B; // 等同于 char a 66;
char b C; // 等同于 char b 67;
printf(%d\n, a b); // 输出133常见的ASCII值与对应的字符如下(ASCII数值范围为0-127) ASCII码上个世纪60年代美国制定了一套字符编码对英语字符与二进制位之间的关系做了统一规定。这被称为ASCII码。ASCII码一共规定了128个字符的编码比如空格“SPACE”是32二进制00100000大写的字母A是65二进制01000001。这128个符号包括32个不能打印出来的控制符号只占用了一个字节的后面7位最前面的1位统一规定为0也就是说ASCII虽然用8位二进制编码表示字符但是其有效位为7位。 举例1字符′1′和整数1是不同的概念。参看ASCII码表
char c1 1;
char c2 1;
printf(c1 %d\n,c1); // c1 1
printf(c2 %d\n,c2); // c2 49举例2
char c?; //定义c为字符型变量并使初值为字符?。?的ASCII代码是63系统把整数63赋给变量c。
printf(%d %c\n,c,c); //用%d格式输出十进制整数63用%c格式输出字符?signed 和 unsigned 修饰
根据C90标准C语言允许在关键字char前面使用signed或unsigned。
signed char c; // 范围为 -128 到 127
unsigned char c; // 范围为 0 到 255注意C 语言规定 char 类型默认是否带有正负号由当前系统决定这一点与 int 不同 int 等同于 signed int 。这就是说 char 不等同于signed char 它有可能是 signed char范围-128 到 127 也有可能是 unsigned char 范围0 到255。不管是哪种范围都正好都能覆盖 0 到 127 的 ASCII 字符范围。
表示方式3使用转义字符
单引号本身也是一个字符如果要表示这个字符常量必须使用反斜杠转义。
char t \;char还可以用来表示转义字符。比如
字符形式含义\n换行符光标移动到下行行首\t水平制表符光标移到下一个Tab位置\单引号字符 ’\双引号字符 \\反斜杠字符 ’\’\r回车符光标移到本行开头\0null 字符代表没有内容。注意这个是等于0而不等于’0‘\b退格键光标回退一个字符但不删除字符
4.4 布尔类型
C语言标准C89没有为布尔值单独设置一个类型所以在判断真假时使用整数 0 表示假所有非0表示真。比如
int main(){int handsome 1;if (handsome) {printf(我好帅!\n);}return 0;
}上述做法不直观可以借助于C语言的宏定义处理。比如
// 定义布尔类型的宏
#define BOOL int //可以使用 typedef int BOOL; 替换
#define TRUE 1
#define FALSE 0int main(){BOOL handsome TRUE;if(handsome){printf(好帅~);}return 0;
}此外C99 标准添加了类型 _Bool表示布尔值即逻辑值true和false。但是这个类型的值其实只是整数类型的别名还是使用 0 表示false 1 表示true其它非0的值都会被存储为1。所以_Bool类型实际上也是一种整数类型。
#include stdio.hint main() {_Bool isFlag 1;if (isFlag)printf(你好毒~~\n);return 0;
}与此同时C99还提供了一个头文件 stdbool.h文件中定义了bool代表_Bool并且定义了 true 代表 1 、 false 代表 0 。只要加载这个头文件就可以使用 bool 定义布尔值类型以及 false 和 true 表示真假。
#include stdio.h
#include stdbool.hint main() {bool isFlag true;if (isFlag)printf(你好毒~~\n);return 0;
}【武汉科技大学2019研】 以下选项中不属于C语言类型的是 。 Ashort int Bunsigned long int Cchar Dbool 【答案】D 【解析】C语言中没有bool型只有C才有boolean型也称bool。C语言中一般用“0”表示“假”用“1”表示“真”。 【四川大学2017研】有4个圆塔圆心分别为22、22、22、22圆半径为1。这4个塔的高度为10m塔以外无建筑物。今输入任一点的坐标求该点的建筑高度塔外的高度为零。 【答案】 N-S图如图1所示。 图1 计算某点建筑高度的N-S流程图 程序如下 #includestdio.hint main() {int h 10;float x1 2, y1 2, x2 -2, y2 -2, x3 -2, y3 -2, x4 2, y4 -2;float x, y; //表示随意选中的一个点的坐标float d1, d2, d3, d4; //(x,y)这个点的坐标到各个圆心的距离printf(请输入一个点(x,y));scanf(%f,%f, x, y);d1 (x - x1) * (x - x1) (y - y1) * (y - y1); //求该点到各中心点距离d2 (x - x2) * (x - x2) (y - y2) * (y - y2);d3 (x - x3) * (x - x3) (y - y3) * (y - y3);d4 (x - x4) * (x - x4) (y - y4) * (y - y4); if (d1 1 d2 1 d3 1 d4 1) //判断该点是否在塔外 h 0;printf(该点高度为%d\n, h);return 0;
}5、变量间的运算规则
在C语言编程中经常需要对不同类型的数据进行运算运算前需要先转换为同一类型再运算。为了解决数据类型不一致的问题需要对数据的类型进行转换。
5.1 隐式类型转换
情况1窄类型自动转为宽类型
即系统自动将字节宽度较小的类型转换为字节宽度较大的数据类型它是由系统自动转换完成的。 基本数据类型的转换规则如图所示 注意最好避免无符号整数与有符号整数的混合运算。因为这时 C 语言会自动将 signed int 转为unsigned int 可能不会得到预期的结果。 举例1
不同的整数类型混合运算时宽度较小的类型会提升为宽度较大的类型。比如 short 转为 int int 转为 long 等。不同的浮点数类型混合运算时宽度较小的类型转为宽度较大的类型比如 float 转为double double 转为 long double 。
float y 12 * 2; //整数赋值给浮点数变量时会自动转为浮点数。结果24.0//char类型 与 int类型运算会自动提升为 int 。
char c 10;
int i 10;
int j c i; //okshort s1 10;
int num1 s1; //ok
double num2 s1; //okint i 10;
double d1 12.3;
double d2 i d1; //系统自动将i的类型由int转换为double类型故id1结果为double类型double d;
d 2 A 1.5F;举例2
两个相同类型的整数运算时或者单个整数的运算一般来说运算结果也属于同一类型。但是有例外宽度小于 int 的类型先自动提升为 int类型再运算运算结果当然也是int类型 。
char c1 10;
short s1 10;
int i1 c1 s1; //char类型和short类型的变量运算的结果默认为int类型unsigned char a 1;
unsigned char b 255;
unsigned char c 255;if ((a - 5) 0) //a-5为int类型注意不是unsigneddo_something();if ((b c) 300) do_something();说明表达式 a - 5 和 b c 都会自动转为 int 类型所以函数 do_something() 会执行两次。
情况2宽类型赋值给窄类型
字节宽度较大的类型赋值给字节宽度较小的变量时会发生类型降级自动转为后者的类型。这时可能会发生截值truncation系统会自动截去多余的数据位导致精度损失。 这反映了C语言在检查类型匹配方面不太严格。最好不要养成这样的习惯。 举例1
double pi 3.14159;
int i pi; // i 的值为 3C编译器把浮点数转换成整数时会直接丢弃截断小数部分而不进行四舍五入。
举例2
int x 3.14; //浮点数赋予整数变量时C 语言直接丢弃小数部分。结果 3int cost 12.99; // double类型的值转为int类型,结果为12
float pi 3.1415926536; // double类型的值转为float类型,结果为3.141593举例3
int i 322;
char ch i; // ch 的值是 66图示 举例4
float f1 1.1f; //ok
double d2 4.58667435;
f1 d2; // 出现精度损失 (double - float )printf(f1%.8f, f1); // 输出f14.58667421
由于存在精度限制浮点数只是一个近似值它的计算是不精确的。
举例5
float a 3.14159; //3.14159为双精度浮点常量分配8个字节a为float变量分配4个字节编译时系统会发出警告(Warning: Narrowing conversion from ‘double’ to ‘float’)提醒用户注意这种转换可能损失精度。
5.2 强制类型转换
隐式类型转换中的宽类型赋值给窄类型编译器是会产生警告的提示程序存在潜在的隐患。如果非常明确地希望转换数据类型就需要用到强制(或显式)类型转换。
形式 (类型名称)(变量、常量或表达式)
功能将“变量、常量或表达式”的运算结果强制转换为“类型名称”所表示的数据类型。
注意强制类型转换会导致精度损失。
举例
double x 12.3;
int y 10;
int z (int)x y; //将变量x的值转换成int后,再与y相加将浮点数转换为整数时将舍弃浮点数的小数部分只保留整数部分。
float f1,f2;
f1 (int)1.2 3.4;
f2 (int)(1.2 3.4);
printf(f1%f,f2%f,f1,f2);输出结果f14.4f24.0。
举例2
int i 40000;
short s (short)i;
printf(%d\n,s); //-25536举例3
long y (long) 10 12; // (long) 将 10 显式转为 long 类型。这里的显示转换其实是不必要的,因为可以自动转换5.3 运算的溢出问题
每一种数据类型都有数值范围如果存放的数值超出了这个范围小于最小值或大于最大值需要更多的二进制位存储就会发生溢出。大于最大值叫做向上溢出overflow小于最小值叫做向下溢出underflow。
一般来说编译器不会对溢出报错会正常执行代码但是会忽略多出来的二进制位只保留剩下的位这样往往会得到意想不到的结果。所以应该避免溢出。
举例1
unsigned char x 255;
x x 1;
printf(%d\n, x); // 0x 是 unsign char 类型最大值是255 二进制 11111111 加 1 后就发生了溢出 256 二进制 100000000 的最高位 1 被丢弃剩下的值就是 0 。
举例2
unsigned int ui UINT_MAX; // 4,294,967,295
ui;
printf(ui %u\n, ui); // 0
ui--;
printf(ui %u\n, ui); // 4,294,967,295常量 UINT_MAX 是 unsigned int 类型的最大值。如果加 1 对于该类型就会溢出从而得到 0 而 0 是该类型的最小值再减 1 又会得到 UINT_MAX 。 溢出很容易被忽视编译器又不会报错所以必须非常小心。 6、常量
6.1 常量分类
程序运行时其值不能改变的量即为常量。
C语言中的常量分为以下以下几种
字面常量#define 定义的标识符常量const 修饰的常变量枚举常量
举例字面常量
1、2、12是整型常量2.1、12.5、3.14是实型常量‘a’、 ‘b’、c’是字符型常量。
#include stdio.hint main(){1;//整型常量3.14;//实型常量a;//字符型常量
}6.2 多种方式定义常量
6.2.1 使用#define
这种方式是在文件开头用 #define 来定义常量也叫作“宏定义”。所谓宏定义就是用一个标识符来表示一个常量值如果在后面的代码中出现了该标识符那么编译时就全部替换成指定的常量值。即用宏体替换所有宏名简称宏替换。
定义格式#define 符号常量名 常量值
符号常量名称为宏名属于标识符一般定义时用大写字母表示。常量值称为宏体可以是数值常量也可以是字符常量。
习惯上宏名用大写字母表示以便于与变量区别。但也允许用小写字母。
举例1
#include stdio.h#define ZERO 0 //#define的标识符常量int main() {printf(zero %d\n, ZERO);return 0;
}跟#include一样“#”开头的语句都是“预处理语句”在编译之前预处理器会查找程序中所有的“ZERO”并把它替换成0这个过程称为预编译处理。 然后将预处理的结果和源程序一起再进行通常的编译处理以得到目标代码 (OBJ文件)。 举例2
#include stdio.h#define PI 3.14 // 定义常量 PI常量值 3.14。因为宏定义不是 C 语句后面不能有分号int main() {//PI 3.1415 可以吗? 不可以double area;double r 1.2;area PI * r * r;printf(面积 : %.2f, area);getchar();return 0;
}
举例3
//函数结果状态代码
#define OK 1
#define ERROR 0
#define OVERFLOW -2#define 对于考研数据结构来说没有什么贡献我们只要认得它就行。 例如1#define MAX_Size 50这句即定义了常量MAX_Size(此时x MAX_Size;等价于x 50;)。 例如2你要定义一个数组如int A[MAX_Size];加上一句注释“/*MAX_Size为已经定义的常量其值为50*/”即可。 6.2.2 使用const限定符
C99中新的声明方式这种方式跟定义一个变量是一样的只需要在变量的数据类型前再加上一个const关键字这被称为“限定符”。
格式
const 数据类型 常量名 常量值;举例
#include stdio.hint main(){//const 修饰的常变量const float PI 3.14f;//PI 5.14;//是不能直接修改的return 0;
}const修饰的对象一旦创建就不能改变所以必须初始化。
跟使用 #define定义宏常量相比const定义的常量有详细的数据类型而且会在编译阶段进行安全检查在运行时才完成替换所以会更加安全和方便。
6.3.3 定义枚举常量
举例
#include stdio.h//使用enum定义枚举类
enum Sex{//括号中的MALE,FEMALE,SECRET是枚举常量MALE,FEMALE,SECRET
};int main(){//枚举常量printf(%d\n, MALE);printf(%d\n, FEMALE);printf(%d\n, SECRET);//注枚举常量默认是从0开始依次向下递增1的return 0;
} 【北京航空航天大学2018研】若已知有如下宏定义 #define CANBERRA(x,y) ((xy)/(xy))则以下表达式中返回结果值最大的是 。 ACANBERRA3.02.0 BCANBERRA4.01.0 CCANBERRA1.02.00.02.0 DCANBERRA1.02.01.01.0 【答案】C 【解析】A项中为1.0/5.0结果为0.2B项中为3.0/5.0结果为0.6C项中的宏替换后为1.02.00.02.0/1.02.002.01.0D项中宏替换后为1.02.01.01.0/1.02.01.01.00.6因此最后答案为C。 【中央财经大学2018研】若有如下宏定义 #define N 2
#define y(n) ((N1)*n)则执行下列语句z4*(Ny(5))后的结果是 。 A语句有错误 Bz值为68 Cz值为60 Dz值为180 【答案】B 【解析】y(5)15z4*(Ny(5))4*1768答案选B。 7、输入/输出函数
所谓输入输出是以计算机主机为主体而言的。
输出从计算机向外部输出设备(显示器、打印机)输出数据。输入从输入设备(键盘、鼠标、扫描仪)向计算机输入数据。 c语言本身没有提供专门的输入输出语句所有的输入输出都是由调用标准库函数中的输入输出函数来实现的。
输入函数scanf() 、 getchar()、gets()
scanf()是格式输入函数可接收任意类型的数据。getchar()是字符输入函数 只能接收单个字符。gets()是字符串输入函数。
输出函数printf() 、 putchar()、puts()
printf()是格式输出函数可按指定的格式显示任意类型的数据。putchar()字符显示函数只能显示单个字符。puts()是字符串输出函数。
7.1 scanf()的使用
scanf()函数的作用把从键盘上输入的数据根据找到的地址存入内存中即给变量赋值。
格式 scanf(格式控制字符串,参数地址列表);
“格式控制字符串”约定输入数据的类型和格式参数的个数必须与变量地址的个数一致。“参数地址列表”以逗号 “, ”分隔的、输入数据变量地址序列。
举例
scanf(%d%d%d,a,b,c)其中a,b,c中的是寻址操作符a表示对象a在内存中的地址。
注意
如果scanf中%d是连着写的如“%d%d%d”在输入数据时数据之间不可以用逗号分隔只能用空白字符空格或tab键或者回车键分隔。即“2(空格)3(tab)4” 或 “2(tab)3(回车)4”等。如果是“%d,%d,%d”则在输入数据时需要加“,”如“2,3,4”。
举例1计算圆的面积其半径由用户指定
#include stdio.hint main() {float radius, area;printf(请输入半径值 );scanf(%f, radius); //输入半径area 3.14 * radius * radius;printf(area%f\n, area); //输出圆的面积return 0;
} 注意变量名之前要加上运算符表示取变量的地址如“ab”。否则将会出现错误。 举例2输入一个整数求其绝对值。
#include stdio.hint main() {int num;printf(输入一个整数:);scanf(%d, num);int absNum num;if(absNum 0)absNum -absNum;printf(\n 整数:%d---绝对值为:%d\n, num, absNum);return 0;
}举例3输入多个变量的值求乘积
#include stdio.hint main() {int a,b,c;printf(请输入整数a,b:);scanf(%d%d,a,b);ca*b;printf(%d*%d%d\n,a,b,c);return 0;
}【武汉科技大学2019研】若有声明语句int x char y[20] double z则正确的输入语句是 。 Ascanf“%d%c%le\n”xyz Bscanf“%2d%s%lf”xyz Cscanf“%d%s%lf”xyz Dscanf“%d%s%3.2f”xyz 【答案】C 【解析】y为一维数组名指向数组首元素的地址因此不需要再使用取地址运算符AB错误D中%3.2f表示长度为3小数为2位但是小数点也占一位因此D错误答案选C。 7.2 getchar()与putchar()的使用 getchar()输入字符数据 格式getchar()功能从键盘缓冲区读入一个字符 putchar()输出字符 格式 putchar(ch)其中ch是一个字符变量功能从标准输出设备输出一个字符
举例
#include stdio.hint main() {char c 0;putchar(A); //输出单个字符Aputchar(c); //输出变量c的ASCII对应字符putchar(\n); //执行换行效果屏幕不显示
}#include stdio.hint main() {char ch;ch getchar();putchar(ch);return 0;
}7.3 gets()与puts()的使用(超纲)
puts()
在C语言中puts() 是一个用于输出字符串的标准库函数其原型定义在 stdio.h 头文件中。puts() 函数的作用是将一个以 null 字符\0结尾的字符串打印到标准输出通常是控制台上并自动添加一个换行符。
int main() {char str1[]{China\nBeijing};char str2[] helloworld;puts(str1);puts(str2);return 0;
}
注意puts()函数只能用于输出字符串而不能输出其他类型的数据。如果需要输出其他类型的数据应使用 printf() 函数。
gets()
读取标准输入设备输入的字符串直到遇到【Enter】键才结束。
char str[20]; //定义一个数组
gets(str); //获取输入的字符串,存放到字符数组中举例字符串的读写
int main() {char str[15];printf(enter your name:);gets(str); //输入字符串至数组变量strprintf(your name is );puts(str); //输出字符串return 0;
}8、变量按声明位置的分类(后面讲)
变量按照声明的位置可以分为局部变量 和 全局变量。 局部变量 在函数体内定义的变量也称内部变量。局部变量只能在定义它的函数中使用。 全局变量 在函数之外定义的变量称为外部变量外部变量是全局变量也称全程变量。 一个程序中凡是在全局变量之后定义的函数都可以使用在其之前定义的全局变量。
举例
#include stdio.hint global 2023;//全局变量
int main(){int local 2022;//局部变量//下面定义的global会不会报错int global 2024;//局部变量printf(global %d\n, global);return 0;
}当局部变量和全局变量同名的时候局部变量优先使用。 9、常见的进制
9.1 二进制概述
计算机底层如何存储数据呢 计算机世界中只有二进制所以计算机中存储和运算的所有数据都要转为二进制。包括数字、字符、图片、声音、视频等。 世界上有10种人 认识和不认识二进制的。 二进制的由来
二进制是计算技术中广泛采用的一种数制由德国数理哲学大师莱布尼茨于1679年发明。
二进制数据是用0和1两个数码来表示的数。它的基数为2进位规则是“逢二进一”。
二进制的应用
二进制广泛应用于我们生活的方方面面。比如广泛使用的摩尔斯电码Morse Code它由两种基本信号组成短促的点信号“·”读“滴”保持一定时间的长信号“—”读“嗒”。然后组成了26个字母从而拼写出相应的单词。 我们偶尔会看到的SOS即为 9.2 进制的分类 十进制decimal 数字组成0-9进位规则满十进一C 语言的整数默认都是十进制数 二进制binary 数字组成0-1进位规则满二进一以0b或0B开头 int x 0b101010;八进制octal很少使用 数字组成0-7进位规则满八进一以数字0开头表示 int a 012; // 八进制相当于十进制的10
int b 017; // 八进制相当于十进制的15十六进制 数字组成0-9a-f进位规则满十六进一以0x或0X开头表示。此处的 a-f 不区分大小写 int a 0x1A2B; // 十六进制相当于十进制的6699
int b 0X10; // 十六进制相当于十进制的169.3 进制的换算举例
十进制二进制八进制十六进制000011112102231133410044510155611066711177810001089100111910101012a或A11101113b或B12110014c或C13110115d或D14111016e或E15111117f或F16100002010
9.4 输出格式
不同的进制只是整数的书写方法不同不会对整数的实际存储方式产生影响。不同进制可以混合使用比如 10 015 0x20 是一个合法的表达式。
printf() 的进制相关占位符如下 %d 十进制整数。 %o 八进制整数。 %x 十六进制整数。 %#o 显示前缀 0 的八进制整数。 %#x 显示前缀 0x 的十六进制整数。 %#X 显示前缀 0X 的十六进制整数。
int x 100;
printf(dec %d\n, x); // 100
printf(octal %o\n, x); // 144
printf(hex %x\n, x); // 64
printf(octal %#o\n, x); // 0144
printf(hex %#x\n, x); // 0x64
printf(hex %#X\n, x); // 0X649.5 进制间的转换(了解)
9.5.1 二进制如何表示整数 计算机数据的存储使用二进制补码形式存储并且最高位是符号位。 正数最高位是0负数最高位是1 规定1正数的补码与反码、原码一样称为三码合一 规定2负数的补码与反码、原码不一样 负数的原码把十进制转为二进制然后最高位设置为1负数的反码在原码的基础上最高位不变其余位取反0变1,1变0负数的补码反码1
9.5.2 二进制与十进制间的转换 二进制转十进制权相加法
针对于一个字节的数据举例来说 例如1个字节8位 25 原码 0001 1001 反码 0001 1001 --补码 0001 1001 -25 原码 1001 1001 反码1110 0110 补码 1110 0111
整数
正数25 00000000 00000000 000000000 00011001原码
正数25 00000000 00000000 000000000 00011001反码
正数25 00000000 00000000 000000000 00011001补码负数-25 10000000 00000000 000000000 00011001原码
负数-25 11111111 11111111 111111111 11100110反码
负数-25 11111111 11111111 111111111 11100111补码一个字节可以存储的整数范围是多少
//1个字节8位0000 0001 ~ 0111 111 1~1271000 0001 ~ 1111 1111 -127 ~ -10000 0000 01000 0000 -128特殊规定-127-1十进制转二进制
十进制转二进制除2取余的逆 9.5.3 二进制与八进制、十六进制间的转换
二进制转八进制 二进制转十六进制 八进制、十六进制转二进制 练习以下叙述中错误的是 。 AC程序在运行过程中所有计算都以十进制方式进行 BC程序在运行过程中所有计算都以二进制方式进行 C所有C程序都需要编译链接无误后才能运行 DC程序中字符变量存放的是字符的ASCII值 【答案】A 【解析】C程序在运行过程中所有计算都以二进制方式进行。答案选择A选项。 【华南理工大学2018研】与十进制1100等值的十六进制数是 。 A44A B44C C54A D54C 【答案】B 【解析】1100转换成二进制为0100 0100 1100因此转换为十六进制为44C。