提示:学习 C 语言的基本数据类型和指针操作
目录
3.15.1 C语言传递参数(或者赋值)可以是值传递(pass by value),也可以传递指针(a pointerpassed by value), 传递指针也叫地址传递。
前言
C 语言作为一种通用的编程语言,以其简洁、高效和灵活的特点在计算机科学领域中占据了重要地位。C 语言不仅在系统编程中广泛应用,同时也是学习其他高级语言的基础。掌握 C 语言的基本数据类型和指针操作,对于理解内存管理、算法实现以及程序性能优化至关重要。
3.1 为什么需要变量
3.1.1 变量是程序的基本组成单位
不论是使用哪种高级程序语言编写程序,变量都是其程序的基本组成单位,比如:
void main() {
int a = 1; // 定义了一个整型变量,取名为 a, 并赋值为 1 (强数据类型语言)
int b = 3; // 定义了一个整型变量,取名为 b, 并赋值为 3 b = 89; // 给变量赋值为 89 printf("a=%d \n", a); // 使用输出语句,把变量 a 值输出 %d 表示输出的形式为整数 printf("b=%d \n", b); // 使用输出语句,把变量 b 值输出 %d 表示输出的形式为整数 getchar(); // 将控制台停留,等待输入
}
该代码的示意图如下:
内存地址 | 变量名 | 值
------------------------
0x7fff5fbff7c4 | a | 1
0x7fff5fbff7c8 | b | 89
3.2 变量的介绍
3.2.1 概念
变量相当于内存中一个数据存储空间的表示。你可以把变量看做是一个房间的门牌号,通过门牌号我们可以找到房间,而通过变量名可以访问到变量(值)。
3.2.2 变量使用的基本步骤
- 声明变量
int num;
- 赋值
num = 60;
- 使用
printf("num=%d", num);
- 也可以一步到位
int num2 = 99;
3.3 变量快速入门
3.3.1 变量使用入门案例
看演示并对代码进行说明:
#include <stdio.h>
void main()
{
int num = 1; // 整型
double score = 2.3; // 小数
char gender = 'A'; // 字符
char name[] = "尚硅谷"; // 字符串
// 说明
// 1. 如果输出的整数 %d
// 2. 如果输出的是小数 %f, 如果希望保留小数点 %.2f
// 3. 如果输出的是字符 %c
// 4. 如果输出的是字符串 %s
// 5. 在输出不同数据时,对应的格式化的形式要对应起来
printf("num=%d score=%.2f gender=%c name=%s", num, score, gender, name); getchar();
}
该代码的示意图如下:
内存地址 | 变量名 | 值
--------------------------------
0x7fff5fbff7c4 | num | 1
0x7fff5fbff7c8 | score | 2.3
0x7fff5fbff7cc | gender | 'A'
0x7fff5fbff7d0 | name | "尚硅谷"
3.4 变量使用注意事项
- 变量表示内存中的一个存储区域(不同的数据类型,占用的空间大小不一样)。
- 该区域有自己的名称和类型。
- 变量必须先声明,后使用。
- 该区域的数据可以在同一类型范围内不断变化。
- 变量在同一个作用域内不能重名。
- 变量三要素(变量名+值+数据类型),这一点请大家注意。
代码演示
#include <stdio.h>
void main() {
//1.变量必须先声明,后使用
//num = 10; //未定义标识符 num
//int num;
//2.该区域的数据可以在同一类型范围内不断变化
int num = 90;
//3. 变量在同一个作用域内不能重名
//4. 变量有三个要素 (变量名 num2 变量值 35, 数据类型 int)
int num2 = 35; //“num”: 重定义
num = 60;
num = 56;
num = 3.4; //从“double”转换到“int”,可能丢失数据
printf("num=%d", num);
getchar();
}
3.5 变量的数据类型
- 每一种数据都定义了明确的数据类型,在内存中分配了不同大小的内存空间(使用字节多少表示)。
- 数据类型一览图
3.数据类型的小结
- 注意:在 C 中,没有字符串类型, 使用字符数组表示字符串。
- 在不同系统上,部分数据类型字节长度不一样, int 可能为 2 或 4 字节。
3.6 整数类型
3.6.1 基本介绍
C 语言的整数类型就是用于存放整数值的,比如 12, 30, 3456 等等。
3.6.2 案例演示
int num = 10;
3.6.3 整型的类型
类型 | 存储大小 | 值范围 |
---|---|---|
int | 4 字节 | -2^31 ~ 2^31-1 |
short | 2 字节 | -2^15 ~ 2^15-1 |
long | 4 字节 | -2^31 ~ 2^31-1 |
long long | 8 字节 | -2^63 ~ 2^63-1 |
3.6.4 整型的使用细节
- 各种类型的存储大小与操作系统、系统位数和编译器有关,目前通用的以 64 位系统为主。
- 在实际工作中,C 程序通常运行在 Linux/Unix 操作系统下,二级考试,使用 Windows。
- C 语言的整型类型,分为有符号 signed 和无符号 unsigned 两种,默认是 signed。
- C 程序中整型常声明为 int 型,除非不足以表示大数,才使用 long long。
- bit(位):计算机中的最小存储单位。byte(字节):计算机中基本存储单元。 1 byte = 8 bit。
示意图:
- short 3 在内存中占有 2 字节
- int 3 在内存中占有 4 个字节
3.7 浮点类型
3.7.1 基本介绍
C 语言的浮点类型可以表示一个小数,比如 123.4, 7.8, 0.12 等等。
3.7.2 案例演示
void main() {
double salary = 10000.56;
double num1 = 1.3;
double num2 = 4.5;
double sum = num1 + num2;
printf(" sum = %.2f" , sum);//
getchar();
}
3.7.3 浮点型的分类
类型 | 存储大小 | 精度 |
---|---|---|
float | 4 字节 | 6-7 位 |
double | 8 字节 | 15-16 位 |
long double | 10 字节 | 18-19 位 |
3.7.4 说明
- 关于浮点数在机器中存放形式的简单说明,浮点数 = 符号位 + 指数位 + 尾数位,浮点数是近似值。
- 尾数部分可能丢失,造成精度损失。
3.7.5 浮点型使用细节
- 浮点型常量默认为 double 型,声明 float 型常量时,须后加‘f’或‘F’。
- 浮点型常量有两种表示形式:
- 十进制数形式:如 5.12, 512.0f, .512(必须有小数点)
- 科学计数法形式:如 5.12e2、5.12E-2
- 通常情况下,应该使用 double 型,因为它比 float 型更精确。
printf("d1=%f", d1);
在输出时,默认保留小数点 6 位。
#include <stdio.h>
void main() {
//浮点型常量默认为 double 型 ,声明 float 型常量时,须后加‘f’或‘F’
float d1 = 1.18909095; //从“double”到“float”截断, 1.1 是 double
float d2 = 1.1f;//1.1f 就是 float
double d3 = 1.3; // ok
double d4 = 5.12;
double d5 = .512; // 等价 0.512
double d6 = 5.12e2; //等价 5.12 * (10^2) = 512
double d7 = 5.12e-2; // 等价 5.12 * (10^-2) = 5.12 / 100 = 0.0512
//在输出时,如果%f 默认保留小数点 6 位
printf("d1=%.15f d2=%f d3=%f d4=%f d5=%f d6=%f d7=%f", d1,d2,d3,d4,d5,d6,d7);
getchar();
}
3.8 字符类型(char)
3.8.1 基本介绍
字符类型用于表示单个字符,在 C 语言中,字符类型为 char
,它占用 1 个字节的存储空间。多个字符组成的字符串在 C 语言中使用 char
数组表示。数组属于构造类型,不是基本数据类型。
3.8.2 基本案例
void main() {
char c1 = 'A';
char c2 = '0';
char c3 = '\t';
printf("c1=%c c3=%c c2=%c", c1, c3, c2); //%c 表示以字符的形式输出
getchar();
}
3.8.3 字符类型使用细节
- 字符常量用单引号(
''
)括起来,例如:char c1 = 'a';
char c3 = '9';
- 可以使用转义字符
\
来表示特殊字符,例如:char c3 = '\n';
('\n'
表示换行符)。 - 在 C 中,
char
本质上是一个整数,输出时按 ASCII 码对应的字符显示。 - 可以直接给
char
赋值一个整数,输出时按对应的 ASCII 字符显示。 char
类型可以进行运算,相当于一个整数,因为它们有对应的 Unicode 码。-
案例演示
#include <stdio.h>
void main() {
char c1 = 'a';
char c2 = 'b';
//这时当我们以%c 输出时,就会安装 ASCII 编码表(理解 字符 <==> 数字 对应关系 ) 对应的 97 对应字
符输出
char c3 = 97;
//这里注意
//1. vs2010 编译器 是 c89
//2. 要求 变量的定义在 执行语句之前
int num = c2 + 10; // 98 + 10 = 108
printf("c1=%c c2=%c c3=%c", c1, c2, c3);// c3= 'a'
printf("num=%d", num); // 108
getchar();
}
3.8.4 字符类型本质探讨
- 字符型存储在计算机中时,需要将字符对应的码值(整数)存储到内存中。
- 存储过程:字符 'a' → 码值 (97) → 二进制 (1100001) → 存储
- 读取过程:二进制 (1100001) → 码值 (97) → 字符 'a' → 读取
- 字符和码值的对应关系是通过字符编码表决定的(如 ASCII 码)。
3.9 ASCII 码介绍(了解)
- 在计算机内部,所有数据都使用二进制表示。一个字节(byte)由 8 个二进制位(bit)组成,可以组合出 256 种状态,用来表示 256 个不同的符号。
- ASCII 码由美国在上世纪 60 年代制定,用于将英语字符与二进制位统一对应。ASCII 码规定了 127 个字符的编码,比如空格(SPACE)是 32,大写字母 A 是 65。这 128 个符号只占用了一个字节的后面 7 位,最前面的 1 位统一规定为 0。
3.10 布尔类型:boolean
3.10.1 基本介绍
- C 语言标准(C89)没有定义布尔类型,判断真假时以 0 为假,非 0 为真。
- 可以使用宏定义来表示布尔值。
- C 语言标准(C99)提供了
_Bool
类型,C99 还提供了一个头文件<stdbool.h>
,定义了bool
代表_Bool
,true
代表 1,false
代表 0。
- 条件控制语句; if
- 循环控制语句; while ...
3.10.2 应用案例
#include <stdio.h>
//宏定义
#define BOOL int
#define TURE 1
#define FALSE 0
void main() {
int isPass = -1;
//可以使用宏定义来完成(这里大家先看下,体会一下,后面我们会详解宏定义)
//定义一个布尔变量
BOOL isOk = TURE; // 等价 int isOK = 0
if(isPass) { // 0 表示假, 非 0 表示真
printf("通过考试");
}
if(isOk) {
printf("ok");
}
getchar();
}
3.11 基本数据类型转换
3.11.1 自动类型转换
C 语言中,当进行赋值或运算时,精度小的类型会自动转换为精度大的类型。
3.11.2 数据类型按精度(容量)大小排序
从精度小到大排列为:char
< short
< int
< unsigned int
< long
< unsigned long
< float
< double
< long double
3.11.3 自动类型转换规则
- 多种类型混合运算时,系统首先将所有数据转换成精度最大的类型,然后再进行运算。
- 两种类型的字节数不同,转换成字节数大的类型。
- 两种类型的字节数相同,但一种有符号一种无符号,转换成无符号类型。
- 赋值运算中,赋值号两边数据类型不同时,右边类型将转换为左边类型。
3.11.5 自动类型转换细节说明
1) 有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度最大的那种数据类型,然后再进行计算(如int 型和 short 型运算时,先把 short 转成 int 型后再进行运算)。
2) 若两种类型的字节数不同,转换成字节数大的类型,若两种类型的字节数相同,且一种有符号,一种无符号,则转换成无符号类型
3) 在赋值运算中,赋值号两边量的数据类型不同时,赋值号右边的类型将转换为左边的类型,如果右边变量的数据类型长度比左边长时,将丢失一部分数据,这样会降低精度,丢失的部分按四舍五入向前舍入
4) 代码演示
#include <stdio.h>
void main() {
//举例 1
char c1 = 'a';
int num1 = c1; //ok
double d1 = num1; //ok
//ok
//举例 2
short s1 = 10;
int num2 = 20;
int num3 = s1 + num2; //ok
//举例 3
float f1 = 1.1f; //ok
double d2 = 4.58667435;
f1 = d2; // 出现精度损失 (double -> float )
printf("f1=%.8f", f1); // 期望: 4.58667435
getchar();
}
3.11.6 强制类型转换
- 介绍
将精度高的数据类型转换为精度小的数据类型。使用时要加上强制转换符 ( ),但可能造成精度降低或溢出,格外要注意。
- 强制类型转换用于将高精度的数据类型转换为低精度类型,可能导致精度降低或数据溢出。格式如下:
(类型名) 表达式
- 什么是表达式: 任何有值都可以称为表达式,比如 1+ 2, int num = 2
这种强制类型转换操作并不改变操作数本身
- 案例演示
#include <stdio.h>
void main() {
double d1 = 1.934;
int num = (int)d1; //这里注意,不是进行四舍五入,而是直接截断小数后的部分
//强制转换只对最近的数有效, 如果希望针对更多的表达式转换,使用()
//int num2 = (int)3.5 * 10 + 6 * 1.5; // 3 * 10 + 6 * 1.5 = 30 + 9.0 = 39.0
int num3 = (int)(3.5 * 10 + 6 * 1.5); // 35.0 + 9.0 = 44.0 -> int = 44
printf("\nnum3=%d", num3); // num3 = 44
printf("\nnum=%d d1=%f" , num, d1); // d1 仍然是 double
getchar();
}
3.13 指针入门
3.14 基本介绍
指针表示一个地址(存放的是地址)。指针变量的定义形式为:数据类型 *指针变量名
。
#include <stdio.h>
void main() {
int num = 1;
//定义一个指针变量,指针
//说明
//1. int * 表示类型为 指针类型
//2. 名称 ptr , ptr 就是一个 int * 类型
//3. ptr 指向了一个 int 类型的变量的地址
int *ptr = #
//num 的地址是多少
//说明 1:如果要输出一个变量的地址,使用格式是 %p
//说明 2: &num 表示取出 num 这个变量对应地址
printf("\nnum 的值=%d num 地址=%p", num, &num);
//1.指针变量,本身也有地址 &ptr
//2.指针变量, 存放的地址 ptr
//3.获取指针指向的值 *ptr
printf("\nptr 的地址是 %p ptr 存放的值是一个地址为 %p ptr 指向的值=%d", &ptr, ptr, *ptr);
getchar();
}
3.14.1 指针应用案例
编写一个程序,获取一个 int
变量 num
的地址,并显示到终端,将 num
的地址赋给指针 ptr
,并通过 ptr
修改 num
的值。
#include <stdio.h>
void main() {
//写一个程序,获取一个 int 变量 num 的地址,并显示到终端
//将 num 的地址赋给指针 ptr , 并通过 ptr 去修改 num 的值.
//分析 ptr 的类型 是 int * , 注意指针的类型和 该指针指向的变量类型是对应关系
//并画出案例的内存布局图
//int num = 88;
//int * ptr = #
先输出 num 没有修改的情况
//printf("\nnum 的值=%d num 的地址=%p", num, &num); // num= 88
//*ptr = 99; // 通过 ptr 去修改 num 的值, num 变量的值也就相应的被修改
//printf("\n num 的值=%d num 的地址=%p", num, &num);// num = 99
int a = 300; // a = 300
int b = 400; // b = 400
int * ptr = &a; //ok ptr 指向 a
*ptr = 100; // a = 100
ptr = &b; // ok ptr 指向 b
*ptr = 200; // b = 200
printf("\n a=%d,b=%d,*ptr=%d", a, b, *ptr); //a = 100, b = 200, *ptr = 200
getchar();
getchar();
}
3.14.3 指针细节说明
1) 基本类型,都有对应的指针类型, 形式为 数据类型 *,比如 int 的对应的指针就是 int *, float 对应的指针类型就是 float * , 依次类推。
2) 此外还有指向数组的指针、指向结构体的指针,指向共用体的指针,(二级指针,多级指针)后面我们再讲到数组、结构体和共用体时,还会详细讲解。
3.15 值传递和地址传递
3.15.1 C语言传递参数(或者赋值)可以是值传递(pass by value),也可以传递指针(a pointerpassed by value), 传递指针也叫地址传递。
1) 默认传递值的类型:基本数据类型 (整型类型、小数类型,字符类型), 结构体, 共用体。
2) 默认传递地址的类似:指针、数组
3.15.2 值传递和地址传递使用特点:
1) 值传递:将变量指向的存储内容,在传递/赋值时,拷贝一份给接收变量.
2) 地址传递 也叫 指针传递:如果是指针,就将指针变量存储的地址,传递给接收变量,如果是数组,就将数组的首地址传递给接收变量。
3) 代码演示
|
总结
在本章节中,介绍了 C 语言中字符类型和布尔类型的使用、基本数据类型的自动和强制类型转换,以及指针的基本概念和应用。通过实际代码示例,我们了解到以下关键点:
-
字符类型(char):字符类型用于表示单个字符,占用 1 个字节,C 语言中字符实际是整数,输出时按 ASCII 码对应字符显示。可以使用转义字符表示特殊字符。
-
布尔类型(boolean):C89 标准没有布尔类型,判断真假时以 0 为假,非 0 为真。C99 标准引入了
_Bool
类型,可以通过stdbool.h
头文件方便地使用布尔类型。 -
基本数据类型转换:当进行赋值或运算时,精度小的类型会自动转换为精度大的类型。需要注意的是,强制类型转换可能导致精度损失或数据溢出。
-
指针:指针用于存储变量的地址,是 C 语言中一个重要的概念。理解指针对于掌握内存管理和高效编程至关重要。通过指针可以间接访问和修改变量的值。
通过对这些内容的学习,可以更好地理解 C 语言的基本数据结构和内存操作,为编写复杂程序奠定基础。
附录
参考:【尚硅谷C语言零基础快速入门教程-哔哩哔哩】 https://b23.tv/vS3vTDp