目录
一、学习目标:
知识点:
- 一文掌握 C 语基础数据类型
- 掌握常量变量运用、输入输出等操作
- 简单了解内存大小计算和类型转换
二、数据基本类型
整型
- 概念:表达整数类型的数据
- 语法:
int a = 123;
// 定义了一个专门用来存储整数的变量a
- 需要注意的地方:
- int 的本意是 integer,即整数的意思
- int a 代表在内存中开辟一块小区域,称为 a,用来存放整数,a 一般被称为变量。
- 变量 a 所占内存大小,在不同的系统中是不一样的,64位 32 位 系统典型的大小是4个字节
- 变量 a 有固定的大小,因此也有取值范围,典型的范围是:-2147483648到2147483647
- 整型修饰符
- short:用来缩短整型变量的尺寸,减少取值范围并节省内存,称为短整型
- long:用来增长整型变量的尺寸,增大取值范围并占用更多内存,称为长整型
- long long:用来增长整型变量的尺寸,增大取值范围并占用更多内存,称为长长整型
- unsigned:用来去除整型变量的符号位,使得整型变量只能表达非负整数
short int a; // 短整型
long int b; // 长整型
long long int c; // 长长整型
unsigned int e; // 无符号整型
unsigned short int f; // 无符号短整型
unsigned long int g; // 无符号长整型
unsigned long long int h; // 无符号长长整型
- 使用整型修饰符后,关键字 int 可以被省略:
short a; // 短整型
long b; // 长整型
long long c; // 长长整型
unsigned e; // 无符号整型
unsigned short f; // 无符号短整型
unsigned long g; // 无符号长整型
unsigned long long h; // 无符号长长整型
- 符号位:
- 有符号的整型数据,首位(最高位)为符号位,0表示正数,1表示负数。
- 无符号的整形数据,没有符号位。
- 编码形式:
- 原码:正数直接使用二进制来表达,比如a=100,在内存中是 00…001100100
- 补码:负数用绝对值取反加一来表达,比如a=-3,在内存中是11…1111111101
- 补码 = 该负数的绝对值的源码 --> 取反 --> + 1
- 注意负数的补码在取反加一的时候,符号位是不动的
- 溢出:超过数据所能表达的范围,称为溢出,就像汽车里程表,最大值和最小值是相邻的
- 进制:源码中可以使用八进制、十进制或十六进制,但实际数据在内存中一律是二进制存储
- 十进制(默认),比如1099
- 八进制,比如013 (这里的0 是八进制的前缀)
- 十六进制,比如0x6FF0A (0x 则是16进制的前缀)
// 以下3个变量看起来都是 100 但实际由于进制不同则他们表示的数值有有差异:
int a1 = 100 ; int a2 = 0100; int a3 = 0x100 ;
格式控制符
十进制输出: int 整型:%d short 整型:%hd, h代表half,即一半的存储字节 long 整型:%ld long long 整型:%lld 八进制输出: 显示不同进制的前缀: %#o 十六进制输出: %#x
示例:
// 以下3个变量看起来都是 100 但实际由于进制不同则他们表示的数值有有差异
int a1 = 100 ;
int a2 = 0100;
int a3 = 0x1AB ;
printf("a1:%d a2:%d a3:%d\n" , a1 , a2 , a3); // %d 十进制输出整形
printf("a1:%#x a2:%#x a3:%#X\n" , a1 , a2 , a3); // %x 十六进制输出整形 # 则可以输出十六进制的前缀0x
// x 可以是大写也可以是小写,对应的是十六进制中字符的大小写
// %#x -> 0xab
// %#X -> 0XAB
short s ;
int i ;
long l ;
long long ll ;
printf( "s:%d\n" , s );
printf( "i:%d\n" , i );
printf( "l:%ld\n" , l );
printf( "ll:%lld\n" , ll );
浮点型 / 实型
- 概念:用来表达实数的数据类型
- 分类:
- 单精度浮点型(float),典型尺寸是4字节
- 双精度浮点型(double),典型尺寸是8字节
- 长双精度浮点型(long double),典型尺寸是16字节
- 占用内存越多,能表达的精度越高
float f1; // 单精度
double f2; // 双精度
long double f3; // 长双精度
1234.5678 -> 1.2345678*10^3
0.0001234567 -> 1.234567*10^-4
字符
实际上他就是一个单字节的整形,也可以与整形一样参与运算。
char ch1 = 'a'; // 'a'是字符常量,代表字母a的ascii值 97 char ch2 = '\n'; // '\n'是不可见字符常量,代表回车
计算机中存储的都是1和0,因此各种字符都必须被映射为某个数字才能存储到计算机中,这种映射关系形成的表称为 ASCII 码表。
字符本质上就是一个单字节的整型,支持整型所有的运算。
比如:
char c1 = 20;
char c2 = c1 + 'a'; // 等价于 char c2 = 20 + 97;
printf("%c\n", c2); // 以字符形式输出117,即 'u'
printf("%d\n", c2); // 以整型形式输出117
字符串
- 定义
// 字符串的定义方式有两种:指针和数组
char *s1 = "abcd"; // 使用字符指针来指向一个字符串
char s2[]= "abcd"; // 使用字符数组来存储字符串
// 注意,使用数组来定义字符串时,方括号[]里面的数字可以省略
// 不省略也可以,但必须必字符串实际占用的内存字节数要大,比如:
char s3[] = "apple";
- 在内存中的存储
- 在内存中实际上是多个连续字符的组合
- 任何字符串都以一个 ‘\0’ 作为结束标记,例如:“funny story” 的内存如下
布尔型数据
- 概念:布尔型数据只有真、假两种取值,非零为真,零为假。
- 语法:
bool a = 1; // 逻辑真,此处1可以取其他任何非零数值
bool b = 0; // 逻辑假
- 注意:
- 逻辑真除了 1 之外,其他任何非零数值都表示逻辑真,等价于 1。
- 使用布尔型 bool 定义变量时需要包含系统头文件 stdbool.h。
- 布尔型数据常用语逻辑判断、循环控制等场合。
三、重要的杂七杂八知识点
常量与变量
- 概念:不可改变的内存称为常量,可以改变的内存称为变量
举例:
int a = 100; // a是变量,而100是常量 float f = 3.14; // f是变量,而3.14是常量 char s[] = "abcd"; // s是变量,"abcd"是常量
- 常量的类型
常量举例 | 说明 | 类型 |
100 | 整型 | int |
100L | 长整型 | long |
100LL | 长长整型 | long long |
100ULL | 无符号长长整型 | unsigned long long |
3.14 | 双精度浮点型 | double |
3.14L | 长双精度浮点型 | long double |
‘a’ | 字符型 | char |
“abcd” | 字符指针(字符串) | char * |
标准输入
- 概念:键盘是系统的标准输入设备,从键盘中输入数据被称为标准输入
- 相关函数:
scanf(); // 格式化输入函数
fgets(); // 字符串输入函数
int a;
float f;
scanf("%d", &a); // 从键盘输入一个整型,放入指定的内存地址 &a 中
scanf("%f", &f); // 从键盘输入一个浮点数,放入指定的内存地址 &f 中
scanf("%d%f", &a, &f); // 从键盘依次输入一个整型和一个浮点型数据,用空白符隔开
char c;
char s[10];
scanf("%c", &c); // 从键盘输入一个字符,放入指定的内存地址 &f 中
scanf("%s", s ); // 从键盘输入一个单词,放入指定的数组 s 中(注意不是&s)
fgets(s, 10, stdin); // 从键盘输入一行字符串,放入数组 s 中
- 注意1:
- scanf() 与 printf() 不同,scanf() 的格式控制串不可乱写,尤其是结尾处的 \n
- 用户必须完全按照 scanf() 中描述的输入格式控制串来输入数据,否则将出错。
- 示例:
// 此处输入时必须带逗号
scanf("%d,%d", &a, &b);
// 此处必须先输入a=,然后才能输入整数
scanf("a=%d", &a);
// 此处结束输入时按下的回车符将被scanf()误以为格式控制符,无法正常结束输入
scanf("%d\n", &a);
实例:
#include <stdio.h>
int main(int argc, char const *argv[])
{
int i = 0;
char ch = 0;
float f = 0;
char buf [32] = {0};
// 如下所示,如果在输入多项数据的时候, 从左往右第一项不匹配后会导致往后的所有项目输入终止
int ret_val = scanf( "a=%d ch=%c f=%f buf=%s" , &i , &ch , &f , buf );
// 如果输入表达式如上所示使用空格进行分割各种类型的控制符,那么在输入的时候可以匹配空格 、 Tab 、 回车
// 如果 scanf( "%d,%s,%c" , ...); 这么写在输入时就必须使用 ,(逗号) 进行分割
// 注意千万不要手贱在 格式控制符中加上 \n 不然会出现迷惑现象,必须多输入一个无用的数据+\n才能解脱
printf("成功输入:%d项数据..\n" , ret_val);
printf("i:%d ch:%d f:%f buf:%s\n" , i , ch , f , buf );
return 0;
}
总结:
-
- sacnf 它默认从指定的文件(默认是标准输入文件)中获取指定格式的数据。
- 格式包含 数据的类型(%d %s %c %f ..) 以及 样式(a=%d ch=%c \ %d,%c,%f)
- 如果输入样式中各项数据使用 空格分隔则与之匹配的符号可以是 空格 、 TAB 、 回车
- 如果用户输入的数据不匹配则scanf 会立马停止工作,剩余的数据会留在缓冲区
拓展:
sizeof运算符:
int a = 123 ;
printf("%ld\n" , sizeof a );// 当使用sizeof 求某一个变量的大小时可以省略括号
printf("%ld\n" , sizeof (a) );
printf("%ld\n" , sizeof(int) );
printf("short: %ld\n" , sizeof(short) ); // 2
printf("int :%ld\n" , sizeof(int) ); // 4
printf("long : %ld\n" , sizeof(long) ); // 4(32位系统) / 8(64位系统)
printf("long long :%ld\n" , sizeof(long long ) ); // 8 (32 \ 64 位系统)
类型转换
- 概念:不一致但相互兼容的数据类型,在同一表达式中将会发生类型转换。
- 转换模式:
- 隐式(默认)转换:系统按照隐式规则自动进行的转换
- 强制(手动)转换:用户显式自定义进行的转换
- 隐式规则:从小(低精度)类型向大(高精度)类型转换,目的是保证不丢失表达式中数据的精度
隐式转换示例代码
char a = 'a'; int b = 12; float c = 3.14; float x = a + b - c;
// 在该表达式中将发生隐式转换,所有操作数被提升为float
- 强制转换:用户强行将某类型的数据转换为另一种类型,此过程可能丢失精度
char a = 'a'; int b = 12; float c = 3.14; float x = a + b - (int)c;
// 在该表达式中a隐式自动转换为int,c被强制转为int
不管是隐式转换,还是强制转换,变换的都是操作数在运算过程中的类型,是临时的,操作数本身的类型不会改变,也无法改变。
数据类型的本质
- 概念:各种不同的数据类型,本质上是用户与系统对某一块内存数据的解释方式的约定。
- 推论:
- 类型转换,实际上是对先前定义时候的约定,做了一个临时的打破。
- 理论上,可以对任意的数据做任意的类型转换,但转换之后的数据解释不一定有意义。
17620828909 电话
17620828909 余额
int a = 123 ;
float 123
整型数据尺寸
- 概念:整型数据尺寸是指某种整型数据所占用内存空间的大小
- C语言标准并未规定整型数据的具体大小,只规定了相互之间的 “ 相对大小 ” ,比如:
- short 不可比 int 长 , 一般short为int 的一半
- long 不可比 int 短
- long 型数据长度等于系统字长
- 系统字长:CPU 一次处理的数据长度,称为字长。比如32位系统、64位系统。
- 典型尺寸:
- char 占用1个字节
- short 占用2个字节
- int 在16位系统中占用2个字节,在32位和64位系统中一般都占用4个字节
- long 的尺寸等于系统字长 , 在32位系统中4字节, 在64位系统中8字节
- long long 在32位系统中一般占用8个字节,在64位系统中一般占用8个字节
- 存在问题:
- 同样的代码,放在不同的系统中,可能会由于数据尺寸发生变化而无法正常运行。
- 因此,系统标准整型数据类型,是不可移植的(不具备可移植性),这个问题在底层代码中尤为突出。
可移植性整型
- 概念:不管放到什么系统,尺寸保持不变的整型数据,称为可移植性整型
- 关键:typedef (给现有的类型取别名)
typedef int int32_t; // 将类型 int 取个别名,称为 int32_t
typedef long int64_t;// 将类型 long 取个别名,称为 int64_t
- 思路:
- 为所有的系统提供一组固定的、能反应数据尺寸的、统一的可移植性整型名称
- 在不同的系统中,为这些可移植性整型提供对应的 typedef 语句
#include <stdio.h>
int main(int argc, char const *argv[])
{
long l = 345 ; // 不具备可移植的属性,因在不不同的系统中他的大小有可能发生变化
__int64_t k = 567 ; // 可移植数据类型,在不同的系统中他的大小都是固定的
printf("long:%ld\n" , sizeof(long));
printf("long long :%ld\n" , sizeof(long long));
printf("__int64_t:%ld\n" , sizeof(__int64_t));
return 0;
}
拿下第一个C语言程序
总结
本文介绍了C的一些基本类型知识和类型转换要点,还有变量、常量等其他知识。理解本文所有知识点后,便可编译一个属于自己的小程序,算上是窥得C语皮毛矣