目录
1.2 sizeof 注意事项(获取类型长度 单位“字节”)、计算机存储单位介绍
1.2.1 sizeof 注意事项(获取类型、变量、表达式的长度)
1. C语言提供的各种数据类型
1.1 内置类型细分
数据类型 | 包括 |
字符型 | char // character 1 Byte [signed] char // 有符号的 unsigned char // 无符号的 |
整形 | // 短整型 // 整型 // 长整型 // 更长的整型,C99中引入 |
浮点型 | float // 单精度浮点数 4 Byte double // 双精度浮点数 8 Byte long double // c99 8 Byte |
布尔类型 | _Bool 或者 bool // C99,专门用来表示真和假 // 头文件<stdbool.h> // 1 Byte |
1.2 sizeof 注意事项(获取类型长度 单位“字节”)、计算机存储单位介绍
1.2.1 sizeof 注意事项(获取类型、变量、表达式的长度)
sizeof 操作符的操作数可以是类型,也可是变量或者表达式。
sizeof(类型)
sizeof 表达式
sizeof 的计算结果是size_t 类型的。
sizeof 的操作数如果不是类型,是表达式的时候,可以省略掉后边的括号的。(变量名也属于表达式)
注: sizeof 后边的表达式是不真实参与运算的,根据表达式的类型来得出大小。(解释及举例如下)
sizeof 在代码进行编译的时候,就根据表达式的类型确定了,类型的常用,而表达式的执行却要在程序运行期间才能执行,在编译期间已经将sizeof处理掉了,所以在运行期间就不会执行表达式了。
//测试:sizeof中表达式不计算
#include <stdio.h>
int main()
{
short s = 2;
int b = 10;
printf("%d\n", sizeof(s = b + 1)); // 实际是求的 s 的长度short为 2
printf("s = %d\n", s);
return 0;
}
1.2.2 计算机存储单位介绍
单位 | 换算 |
bit - 比特位 | |
Byte - 字节 | 1 Byte = 8 bit |
KB | 1 KB = 1024 Byte |
MB | 1 MB = 1024 KB |
GB | 1 GB = 1024 MB |
TB | 1 TB = 1024 GB |
PB | 1 PB = 1024 TB |
....... |
2. signed 和 unsigned
C 语言使用 signed 和unsigned 关键字修饰字符型和整型类型的。
整数变量声明为unsigned 的好处是,同样长度的内存能够表示的最大整数值,增大了一倍。
比如,16位的signed short int 的取值范围是:-32768~32767,最大是32767;而unsigned short int 的取值范围是:0~65535,最大值增大到了65,535。32位的signed int 的取值范围可以参看limits.h 中给出的定义。
3. 数据类型和取值范围
上述的数据类型很多,尤其数整型类型就有short、int、long、long long 四种,为什么呢?
其实每一种数据类型有自己的取值范围,也就是存储的数值的最大值和最小值的区间,有了丰富的类型,我们就可以在适当的场景下去选择适合的类型。如果要查看当前系统上不同数据类型的极限值:
limits.h 文件中说明了整型类型的取值范围。
float.h 这个头文件中说明浮点型类型的取值范围。
为了代码的可移植性,需要知道某种整数类型的极限值时,应该尽量使用这些常量。
• 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. 全局变量和局部变量、及存放位置
局部变量不初始化是随机值,全局变量不初始化是0
当局部变量和全局变量同名的时候,局部变量优先使用。
全局变量和局部变量在内存中存储在哪里呢?
一般我们在学习C/C++语言的时候,我们会关注内存中的三个区域:栈区、堆区、静态区。
1. 局部变量是放在内存的栈区
2. 全局变量是放在内存的静态区
3. 堆区是用来动态内存管理的(后期会介绍)
5. 算数操作符(运算符)
双目操作符:此操作符有两个操作数
算数操作符 | 功能 | 注意事项 |
+ | 加 | |
- | 减 | |
* | 乘 | |
/ | 除 | 除号的两端如果是整数,执行的是整数除法,得到的结果也是整数。 如果希望得到浮点数的结果,两个运算数必须至少有一个浮点数,这时 C 语言就会进行浮点数除法。 |
% | 取模(取余数) | 只能用于整数,不能用于浮点数。 负数求模的规则是,结果的正负号由第一个运算数的正负号决定。 |
6. 赋值操作符:= 、连续赋值、复合赋值
在变量创建的时候给一个初始值叫初始化,在变量创建好后,再给一个值,这叫赋值。
6.1 连续赋值
赋值操作符也可以连续赋值,如:
c = b = a+3;//连续赋值,从右向左依次赋值的。
6.2 复合赋值(+=、-+、*=等)
+= -=
*= /= %=
//下面的操作符后期讲解
>>= <<=
&= |= ^=
7. 单目操作符:++、--、+(正)、-(负)
前置++:先+1,后使用
后置++:先使用,后+1
8. 强制类型转换
类型不合适且代码报警高,可以通过强制类型转换消除警告
9. scanf 和 printf 函数
9.1 printf 及 占位符
print:打印
f:fomat(格式化)
9.1.1 占位符列举
printf() 的占位符有许多种类,与 C 语言的数据类型相对应。下面按照字母顺序,列出常用的占位符,方便查找,具体含义在后面章节介绍。
• %a :十六进制浮点数,字母输出为小写。
• %A :十六进制浮点数,字母输出为大写。
• %c :字符。
• %d :十进制整数。
• %e :使用科学计数法的浮点数,指数部分的e 为小写。
• %E :使用科学计数法的浮点数,指数部分的E 为大写。
• %i :整数,基本等同于%d 。
• %f :小数(包含float 类型和double 类型)。
• %g :6个有效数字的浮点数。整数部分一旦超过6位,就会自动转为科学计数法,指数部分的e为小写。
• %G :等同于%g ,唯一的区别是指数部分的E 为大写。
• %hd :十进制 short int 类型。
• %ho :八进制 short int 类型。
• %hx :十六进制 short int 类型。
• %hu :unsigned short int 类型。
• %ld :十进制 long int 类型。
• %lo :八进制 long int 类型。
• %lx :十六进制 long int 类型。
• %lu :unsigned long int 类型。
• %lld :十进制 long long int 类型。
• %llo :八进制 long long int 类型。
• %llx :十六进制 long long int 类型。
• %llu :unsigned long long int 类型。
• %Le :科学计数法表示的 long double 类型浮点数。
• %Lf :long double 类型浮点数。
• %n :已输出的字符串数量。该占位符本身不输出,只将值存储在指定变量之中。
• %o :八进制整数。
• %p :指针。
• %s :字符串。
• %u :无符号整数(unsigned int)。
• %x :十六进制整数。
• %zd : size_t 类型。
• %% :输出一个百分号。
9.1.2 限定宽度
#include <stdio.h>
int main()
{
printf("%5d\n", 123); // 输出为 " 123"
return 0;
}
%5d 表示这个占位符的宽度至少为5位。如果不满5位,对应的值的前面会添加空格。输出的值默认是右对齐,即输出内容前面会有空格;如果希望改成左对齐,在输出内容后面添加空格,可以在占位符的% 的后面插入一个 - 号。
9.1.3 显示正负号
在占位符的% 后面加一个+。
9.1.4 限定小数位数
• %f 小数的默认显示精度是小数点后面6位
• 希望小数点后面只保留两位,占位符可以写成 %.2f
• 可以与限定宽度占位符,结合使用 、
// 输出为 " 0.50"
#include <stdio.h>
int main()
{
printf("%6.2f\n", 0.5);
return 0;
}
上面示例中, %6.2f 表示输出字符串最小宽度为6,小数位数为2。所以,输出字符串的头部有两个空格。
• 最小宽度和小数位数这两个限定值,都可以用 * 代替,通过printf() 的参数传入。
#include <stdio.h>
int main()
{
printf("%*.*f\n", 6, 2, 0.5);
return 0;
}
// 等同于printf("%6.2f\n", 0.5);
// %*.*f 的两个星号通过printf() 的两个参数6 和2 传入。
9.1.5 输出部分字符串
可以用 %.[m]s 指定输出的长度,其中[m] 代表一个数字,表示所要输出的长度。
// 输出 hello
#include <stdio.h>
int main()
{
printf("%.5s\n", "hello world");
return 0;
}
上面示例中,占位符%.5s 表示只输出字符串“hello world”的前5个字符,即“hello”。
9.2 scanf
9.2.1 使用注意事项
1. 注意:变量前面必须加上& 运算符(指针变量除外),因为scanf() 传递的不是值,而是地址,即将变量 i 的地址指向用户输入的值。如果这里的变量是指针变量(比如字符串变量),那就不用加 & 运算符。
2. scanf() 处理数值占位符时,会自动过滤空白字符,包括空格、制表符、换行符等。
9.2.2 返回值及连续输入
• scanf() 的返回值是一个整数,表示成功读取的变量个数。
• 如果没有读取任何项,或者匹配失败,则返回0 。
• 如果在成功读取任何数据之前,发生了读取错误或者遇到读取到文件结尾,则返回常量 EOF。(EOF是 stdio.h 库中的宏定义,值为 -1 )
• 按ctrl+z ,提前结束输入:
• scanf 连续输入方法(根据返回值判断是否继续连续输入)
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
/*while (scanf("%d %d", &a, &b) == 2)
{
int c = a + b;
printf("%d\n", c);
}
*/
while (scanf("%d %d", &a, &b) != EOF)
{
int c = a + b;
printf("%d\n", c);
}
return 0;
}
9.2.3 占位符
• %[] :在方括号中指定一组匹配的字符(比如%[0-9] ),遇到不在集合之中的字符,匹配将会停止。
• 除了%c 以外,都会自动忽略起首的空白字符。%c 不忽略空白字符,总是返回当前第一个字符,无论该字符是否为空格。
• 占位符%s ,它其实不能简单地等同于字符串。它的规则是,从当前第一个非空白字符开始读起,直到遇到空白字符(即空格、换行符、制表符等)为止。
因为%s 不会包含空白字符,所以无法用来读取多个单词,除非多个%s 一起使用。这也意味着,scanf() 不适合读取可能包含空格的字符串,比如书名或歌曲名。另外, scanf() 遇到%s 占位符,会在字符串变量末尾存储一个空字符\0 。
scanf() 将字符串读入字符数组时,不会检测字符串是否超过了数组长度。所以,储存字符串时,很可能会超过数组的边界,导致预想不到的结果。为了防止这种情况,使用 %s 占位符时,应该指定读入字符串的最长长度,即写成%[m]s ,其中的[m] 是一个整数,表示读取字符串的最大长度,后面的字符将被丢弃。
#include <stdio.h>
int main()
{
char name[11];
scanf("%10s", name);
return 0;
}
9.2.4 赋值忽略符
只要把 * 加在任何占位符的百分号后面,该占位符就不会返回值,解析后将被丢弃。
#include <stdio.h>
int main()
{
char name[11];
scanf("%10s", name);
return 0;
}
//%*c 就是在占位符的百分号后面,加入了赋值忽略符* ,表示这个占位符没有对应的变量,解读后不必返回。