0
点赞
收藏
分享

微信扫一扫

C Primer Plus 第3章(数据和C)

yongxinz 2022-02-03 阅读 55
c语言

目录

1. 变量和常量数据

  • 常量(constant):在程序使用前已经设定好,在整个程序的运行过程中不会发生变化

  • 变量(variable):在程序运行期间可能会改变或被赋值

#include <stdio.h>

int main() {
    int i = 1;
    // i: 变量
    // 1: 常量
}

2. 数据:数据类型关键字

初始关键字C90添加关键字C99添加关键字
intsigned_Bool
longvoid_Complex
short_Imaginary
unsigned
char
float
double
  • 位、字节和字
    • 位:bit,用于存储0和1
    • 字节:byte
      • 1byte = 8bits
    • 字:word
      • 根据操作系统的位数决定,位数即为字长
        • 8位系统:1word = 8bits
        • 16位系统:1word = 16bits
        • 32位系统:1word = 32bits
        • 64位系统:1word = 64bits

2.1 整数

正确错误
2、-23、24563.14、0.22、2.000
00000111字长8位
2^22^12^0
4+ 2+ 1= 7整数7

2.2 浮点数

正确错误
2.75、3.16E7、7.00、2e-87
  • E/e 记数法:3.16E7 = 3.16 * 10 ^ 7
+0.3168
符号小数指数
+0.316* 10 ^ 8= 3.16 * 10 ^ 7

2.3 区别

整数浮点数
没有小数部分有小数部分
表示范围较小表示范围较大
对于一些算数计算(两个大数相减)精度损失较小精度损失较大
实际值实际值的近似值
运算较快运算较慢(通过CPU上的浮点处理器弥补)

3. 基本数据类型

3.1 int类型

  • 有符号整型
  • 16位
  • 取值范围:- 2 ^ 31 ~ 2 ^ 31 - 1

3.1.1 获取值的途径

  • 赋值

    int i;
    // 创建内存空间
    i = 1;
    
  • 通过函数获取

    int i;
    scanf("%d", &i);
    
  • 初始化变量

    int i = 1;
    // 创建内存空间,并为其赋值
    

3.1.2 打印

#include <stdio.h>

int main() {
  int i = 1;
  int j = 2;

  printf("i = %d, j = %d\n", i, j);
  // i = 1, j = 2
  
  printf("i = %d, j = %d\n", i);
  // i = 1, j = 11604003
  // j为脏数据
}

3.1.3 八进制和十六进制

  • 八进制:以 0 开头
  • 十六进制:以 0x 或 0X 开头

3.1.4 显示八进制和十六进制

符号含义
%d以十进制显示数字
%o以八进制显示数字
%x 或 %X以十六进制显示数字
%#o以八进制显示数字,并附带前缀
%#x 或 %#X以十六进制显示数字,并附带前缀

3.2 其他整数类型

符号含义
short (int)占用空间比 int 少,有符号整型,16位
long (int)占用空间比 int 多,有符号整型,32位
long long (int)占用空间比 long 多,有符号整型,64位
unsigned (int)无符号整型,0 ~ 2^16 - 1
  • C90添加 unsigned long 和 unsigned short
  • C99添加 unsigned long long
  • 在任何有符号类型前加关键字 signed ,可强调使用有符号类型的意图

3.2.1 long 常量和 long long 常量

  • 使用 l 或 L 后缀表示 long 类型

    int i1 = 1;
    // 16位存储
    
    int i2 = 1l;
    // singned long
    // 32位存储
    
    int j = 2uL;
    // unsigned long
    
  • 使用 ll 或 LL 后缀表示 long long 类型

    int i = 1ll;
    // singned long long
    
    int j = 2uLL;
    // unsigned long long
    

3.2.2 整数溢出

#include <stdio.h>

int main() {
	int i = 2147483647;
	int j = 4294967295u;

	printf("%d, %d, %d\n", i, i+1, i+2);
	// 2147483647, -2147483648, -2147483647
	
	printf("%u, %u, %u\n", j, j+1, j+2);
	// 4294967295, 0, 1
}

3.2.3 打印

符号含义
%ld以十进制打印 long
%lx以十六进制打印 long
%lo以八进制打印 long
%hd以十进制打印 short
%hl以十六进制打印 short
%ho以八进制打印 short
%u打印 unsigned int
%lu打印 unsigned long
%lld以十进制打印 long long
%llu打印 unsigned long long

3.3 使用字符:char类型

  • 存储字符(字母或标点符号)
  • char 实际上存储的是整数而不是字符
  • 计算机用数字编码处理字符
  • 一定为1个字节,即8位

3.3.1 声明

char a;
char b, c;

3.3.2 字符常量和初始化

char a = 'A';
// 初始化
// a: 变量
// 'A': 常量

char a = 65;
// 将 ASCII码 65 对应的字符赋值给 a
语句T / F
a = ‘A’;T
a = A;F,此时 A 为变量
a = “A”;F,此时 “A” 为字符串

难点(坑)(P45)

  • C语言将字符常量视为 int 类型而非 char 类型
  • int:32 位、char:8位
  • 原本字符常量对应的ASCII码存储在32位的存储单元中,现在可以存储在8位的存储单元中
#include <stdio.h>

int main() {
	char a = 'ABCD';
    // 把4个独立的8位ASCII码存储在一个32位存储单元中

	char b = a;
    // 只有最后8位有效

	printf("%c\n", b);
    // D
}

3.3.3 非打印字符

转义字符含义应用
\a警报(ANSI C)发出一声蜂鸣,但不移动光标
\b退格
\f换页将活跃位置移至下一页开始处(可能显示成奇怪的符号)
\n换行将活跃位置移至下一行开始处
\r回车将活跃位置移至当前行开始处
\t水平制表符将活跃位置移至下一个水平制表点
\v垂直制表符将活跃位置移至下一个垂直制表点(可能显示成奇怪的符号)
\反斜杠(\)
\’单引号
\"双引号
\?问号
\0oo八进制(oo为有效的八进制数)使用该八进制数的ASCII码对应的字符
\xhhh十六进制(hhh为有效的十六进制数)使用该十六进制数的ASCII码对应的字符

3.3.4 打印

#include <stdio.h>

int main() {
	char c = ' ';

	scanf("%c", &c);
	// a

	printf("%c = %d\n", c, c);
	// a = 97
}

3.3.5 是否有符号(坑)

  • 不同的编译器对于char的符号类型定义不同
    • 有的编译器把char实现为有符号类型,char可表示范围为 -2^7 ~ 2^7 - 1
    • 有的编译器把char实现为无符号类型,char可表示范围为 0 ~ 2^8 - 1
  • C90标准下,C语言允许在关键字 char 前使用 signed 和 unsigned

3.4 _Bool类型

  • C99标准添加了_Bool 类型,用于表示布尔值,即逻辑 true 和 false
  • C语言使用 1 表示 true,0 表示 false
  • _Bool类型实际上也为一种整数类型,仅占用1位存储空间

3.5 可移植类型:stdint.h 和 inttypes.h

  • C99新增

  • 某些类型名在不同系统中的功能不同,因而引入 stdint.h 和 inttypes.h,以确保C语言的类型在各系统中的功能相同

  • stdint.h:现有类型名的别名

    • 精准宽度整数类型(exact-width integer type):

      • C99提供

      • int32_t:宽度正好是32位的整数类型

      • 计算机的底层系统可能无法支持

    • 最小宽度类型(minimum width type):

      • C99 和 C11 提供

      • int_least8_t:可容纳8位有符号整数值的类型中宽度最小的类型

    • 最快最小宽度类型(fastest minimum width type):

      • C99 和 C11 提供
      • int_fast8_t:系统中对8位有符号值而言运算最快的整数类型
    • 最大整数类型

      • C99提供
      • intmax_t:最大的有符号整数类型
      • uintmax_t:最大的无符号整数类型
  • inttypes.h:字符串宏以用来显示可移植类型

    • PRId32:打印32位有符号值得合适转换说明(d / l)

3.6 float、double 和 long double

  • 浮点数的表示类似于科学记数法,即用小数乘以10的幂来表示数字
例子科学记数法指数记数法
10000000001.0 * 10 ^ 91.0e9
1230001.23 * 10 ^ 51.23e5
322.563.2256 * 10 ^ 23.2256e2
0.0000565.6 * 10 ^ -55.6e-5
  • float:单精度
    • 至少能表示6位有效数字,且取值范围至少为10 ^ -37 ~ 10 ^ 37
    • 通常,系统存储一个 float 要占用32位
      • 8位用于表示指数的值和符号
      • 24位用于表示非指数部分及其符号
  • double:双精度
    • 至少能表示10位有效数字,且取值范围至少为10 ^ -37 ~ 10 ^ 37
    • 通常,系统存储一个 double 要占用64位
      • 有的系统将多出的32位全部用来表示非指数部分,增加有效数字的位数(提高精度),减少舍入误差
      • 有的系统将多出的32位中的一些位表示指数部分,增加可表示数的范围
  • long double:比 double 精度更高
    • C只保证 long double 类型至少与 double 类型的精度相同

3.6.1 声明

float f;
double d;
long double ld;

3.6.2 浮点型常量

  • 编译器假定浮点型常量是 double 类型的精度,计算精度更高,但是减慢程序的运行速度
float f;

f = 1.1;
// 1.1: 常量
// double

f = 1.1f;
// float

f = 1.1L;
// long double
  • C99 添加用十六进制表示浮点型常量
    • 在十六进制前加前缀 0x 或 0X
    • 用 p 或 P 分别代替 e 和 E,用 2 的幂代替 10 的幂
0xa.1fp10
十六进制(10+ 1/16 + 15/256)* 2^ 10= 10364.0

3.6.3 打印

  • 编译器会把 float 类型自动转换成 double 类型
符号含义
%f以十进制记数法打印 float 和 double
%e以指数记数法打印 float 和 double
%a以十六进制记数法打印 float 和 double
%lf以十进制记数法打印 long float 和 long double
#include <stdio.h>

int main() {
	float f = 1.0;
	double d = 2.0;
	long double ld = 3.0;

	printf("%f = %e = %a\n", f, f, f);
	// 1.000000 = 1.000000e+00 = 0x1.0000000000000p+0

	printf("%f = %e\n", d, d);
	// 2.000000 = 2.000000e+00

	printf("%lf = %le\n", ld, ld);
	// 3.000000 = 3.000000e+00
}

3.6.4 浮点值的上溢和下溢

  • 上溢(overflow):
    • 计算导致数字过大,超过当前类型能表达的范围
    • 发生此情况时,C语言会给变量赋一个很大的值,并显示该值为 inf 或 infinity(无穷)
float f = 3.4e38 * 100.0f;

printf("%e\n", f);
// inf
  • 下溢(underflow):
    • 低于正常的(subnormal)浮点值:计算导致数字过小,损失原末尾有效位上的数字
#include <stdio.h>

int main() {
	float f = 0.1234e-2;

	printf("%f / 10 = %f\n", f, f / 10);
    // 0.001234 / 10 = 0.000123
}
  • 特殊的浮点数值:NaN,计算的行为未被定义

3.7 复数和虚数类型

  • C99提供
  • 复数:
    • float_Complex:
      • 包含两个 float 类型的值,分别表示实部和虚部
    • double_Complex
    • long double_Complex
  • 虚数:
    • float_Imaginary
    • double_Imaginary
    • long double_Imaginary
  • 如果包含 complex.h 头文件,可以用 complex 替换 _Complex,imaginary 替换 _Imaginary

3.8 其他类型

  • 数组
  • 指针
  • 结构
  • 联合

3.9 类型大小

  • sizeof():以字节为单位输出指定类型的大小
  • C99 和 C11 提供 %zd 匹配 sizeof() 的返回值类型
  • 不支持 C99 和 C11 的编译器可以使用 %u 和 %lu 代替 %zd
#include <stdio.h>

int main() {
	printf("int : %zd\n", sizeof(int));
	// int : 4

	printf("char : %zd\n", sizeof(char));
	// char : 1

	printf("long : %zd\n", sizeof(long));
	// long : 4

	printf("long long : %zd\n", sizeof(long long));
	// long long : 8
		
	printf("double : %zd\n", sizeof(double));
	// double : 8
	
	printf("long double : %zd\n", sizeof(long double));
	// long double : 8
}

4. 使用数据类型

  • 初始化变量应使用与变量类型匹配的常数类型
示例T / F
int i = 1;T
int i = 1.0;F,可以赋值,不推荐
int i = 1.5;F,可以赋值,只会保留整数位
float f = 3.1415926536;F,可能会警告,只会保留6位有效数字
举报

相关推荐

0 条评论