[Re] 数据类型&变量&算符
主函数&其他函数#
主函数#
一个完整的 C 语言程序,是由一个、且只能有一个 main()
(又称"主函数",必须有) 和若干个其他函数结合而成(可选)。
main()
是 C 语言程序的入口,程序是从 main()
开始执行。
其他函数#
从函数定义的角度看,函数可分为 [系统函数] 和 [用户定义函数]。
- 系统函数,即库函数:这是由编译系统提供的,用户不必自己定义这些函数,可以直接使用它们,如我们常用的打印函数
printf()
。 - 用户定义函数:用以解决用户的专门需要。
第一个程序#
# include<stdio.h>
int main(void) {
printf("HelloWorld\n"); // \n: 回车换行
return 0;
}
include 头文件包含#
#include
的意思是头文件包含,#include <stdio.h>
代表包含stdio.h
这个头文件- std:标准库
- i:输入 input
- o:输出 output
- .h:一个头文件
- 使用 C 语言库函数需要提前包含库函数对应的头文件,如这里使用了
printf()
,需要包含stdio.h
头文件 #include<...>
与#include "..."
的区别<>
表示系统直接按系统指定的目录检索""
表示系统先在""
指定的路径(没写路径代表当前路径) 查找头文件;如果找不到,再按系统指定的目录检索
花括弧、程序体和代码块#
{}
叫代码块,一个代码块内部可以有一条或者多条语句- C 语言每句可执行代码都是
;
分号结尾 - 所有的
#
开头的行,都代表预编译指令,预编译指令行结尾是没有分号的 - 所有的可执行语句必须是在代码块里面
注释#
// ...
叫行注释,注释的内容编译器是忽略的,注释主要的作用是在代码中加一些说明和解释,这样有利于代码的阅读。
/* ... */
叫块注释。块注释是C语言标准的注释方法。
printf 函数#
printf
是 C 语言库函数,功能是向标准输出设备输出一个字符串。
return 语句#
- return 代表函数执行完毕,返回 return 代表函数的终止
- 如果 main 定义的时候前面是 int,那么 return 后面就需要写一个整数;如果 main 定义的时候前面是 void,那么 return 后面什么也不需要写
- 在
main()
中return 0;
代表程序执行成功,return -1;
代表程序执行失败 int main()
和void main()
在 C 语言中是一样的,但 C++ 只接受int main
这种定义方式
数据类型#
C 的关键字#
数据类型#
数据类型的作用:编译器预算对象(变量)分配的内存空间大小。
整型
#include <stdio.h>
int main() {
int a = 123; // 定义变量a,以10进制方式赋值为 123
int b = 0567; // 定义变量b,以8进制方式赋值为 0567
int c = 0xabc; // 定义变量c,以16进制方式赋值为 0xabc
printf("a = %d\n", a);
printf("8进制:b = %o\n", b);
printf("10进制:b = %d\n", b);
printf("16进制:c = %x\n", c);
printf("16进制:c = %X\n", c);
printf("10进制:c = %d\n", c);
unsigned int d = 0xffffffff; // 定义无符号int变量d,以16进制方式赋值
// 有符号整型数据,可以省略 signed
printf("有符号方式打印:d = %d\n", d);
printf("无符号方式打印:d = %u\n", d);
return 0;
}
需要注意的是,整型数据在内存中占的字节数与所选择的操作系统有关。虽然 C 语言标准中没有明确规定整型数据的长度,但 long 类型整数的长度不能短于 int 类型, short 类型整数的长度不能长于 int 类型。
当一个小的数据类型赋值给一个大的数据类型,不会出错,因为编译器会自动转化。但当一个大的类型赋值给一个小的数据类型,那么就可能丢失高位。
字符型
字符型变量用于存储一个单一字符,在 C 语言中用 char 表示,其中每个字符变量都会占用 1 个字节。在给字符型变量赋值时,需要用一对英文半角格式的单引号 ''
把字符括起来。
字符变量实际上并不是把该字符本身放到变量的内存单元中去,而是将该字符对应的 ASCII 编码放到变量的存储单元中。char 的本质就是一个 1 字节大小的整型。
#include <stdio.h>
int main() {
char ch = 'a';
printf("sizeof(ch) = %u\n", sizeof(ch));
printf("ch: %c\n", ch); // 打印字符
printf("ASCII: %d\n", ch); // 打印 'a' 的 ASCII 值
char A = 'A';
char a = 'a';
printf("a = %d\n", a); // 97
printf("A = %d\n", A); // 65
printf("A = %c\n", 'a' - 32); // 小写 a 转大写 A
printf("a = %c\n", 'A' + 32); // 大写 A 转小写 a
ch = ' ';
printf("空字符:%d\n", ch); // 空字符 ASCII 的值为 32
printf("A = %c\n", 'a' - ' '); // 小写 a 转大写 A
printf("a = %c\n", 'A' + ' '); // 大写 A 转小写 a
return 0;
}
实型(浮点型)
实型变量也可以称为浮点型变量,浮点型变量是用来存储小数数值的。在 C 语言中, 浮点型变量分为两种: 单精度浮点数(float)、 双精度浮点数(double), 但是 double 型变量所表示的浮点数比 float 型变量更精确。
由于浮点型变量是由有限的存储单元组成的,因此只能提供有限的有效数字(默认 6 位)。在有效位以外的数字将被舍去,这样可能会产生一些误差。
不以 f 结尾的常量是 double 类型,以 f 结尾的常量(如 3.14f) 是 float 类型。
#include <stdio.h>
int main() {
// 传统方式赋值
float a = 3.1415f; //或 3.1415F
double b = 3.1415926;
// --------- 默认保留六位小数 ---------
printf("a = %f\n", a); // 3.141500
printf("a(保留两位小数) = %.2f\n", a); // 数据会四舍五入
printf("b = %lf\n", b); // 3.141593
// 科学法赋值
a = 3.2e3f; // 3.2*1000 = 3200,e可以写E
printf("a1 = %f\n", a); // 3200.000000
a = 100e-3f; // 100*0.001 = 0.1
printf("a2 = %f\n", a); // 0.100000
a = 3.1415926f;
printf("a3 = %f\n", a); // 3.141593
return 0;
}
常量&变量#
常量
- 在程序运行过程中,其值不能被改变的量
- 常量一般出现在表达式或赋值语句中
- 定义常量
const
关键字修改的变量- 在程序首部用
#define
声明
#include <stdio.h>
// 2. 用 #define 声明一个常量
#define AGE 21.8
int main() {
// 1. const 修饰的变量即为常量
const float PI = 3.14159F;
printf("PI: %f\n", PI);
printf("AGE: %f", AGE);
return 0;
}
变量
- 在程序运行过程中,其值可以改变
- 变量在使用前必须先定义,定义变量前必须有相应的数据类型
运算符#
算术运算符#
赋值运算符#
比较运算符#
C 语言的比较运算中,"真" 用数字 1 来表示,"假"用数字 0 来表示。
逻辑运算符#
位运算符#
4 个位运算符用于整型数据,包括 char 将这些位运算符成为位运算的原因是它们对每位进行操作,而不影响左右两侧的位。请不要将这些运算符与常规的逻辑运算符(&&
、||
和 !
) 相混淆,常规的位的逻辑运算符对整个值进行操作。
按位取反 ~
一元运算符 ~
将每个 1 变为 0,将每个 0 变为 1。
int main(void) {
int a = 1;
// .... 31 个 0 ....
// 0000 ... 00000001
// .... 按位取反 ....
// 1111 ... 11111110
// .... 30 个 0 ....
// 1000 ... 00000010
printf("%d", ~a); // -2
return 0;
}
位与 &
二进制运算符 &
通过对两个操作数逐位进行比较产生一个新值。对于每个位,只有两个操作数的对应位都是 1 时结果才为 1。
int main(void) {
int a = 10;
int b = 67;
// 00001010
// 01000011
// --------
// 00000010
printf("%d", a&b); // 2
return 0;
}
位或 |
二进制运算符 |
通过对两个操作数逐位进行比较产生一个新值。对于每个位,如果其中任意操作数中对应的位为 1,那么结果位就为 1。
int main(void) {
int a = 10;
int b = 67;
// 00001010
// 01000011
// --------
// 01001011
printf("%d", a|b); // 75
return 0;
}
位异或 ^
二进制运算符 ^
对两个操作数逐位进行比较。对于每个位,如果操作数中的对应位有一个是 1(但不是都是 1),那么结果是 1;如果都是 0 或者都是 1,则结果位 0。
int main(void) {
int a = 12;
int b = 67;
// 00001100
// 01000011
// --------
// 01001111
printf("%d", a^b); // 79
return 0;
}
C 也有一个组合的位异或+赋值运算符:^=
val ^= 0377
val = val ^ 0377
左移 <<
左移运算符 <<
将其左侧操作数的值的每位向左移动,移动的位数由其右侧操作数指定。空出来的位用 0 填充,并且丢弃移出左侧操作数末端的位。该操作将产生一个新位置,但是不改变其操作数。左移 n 次等价于乘以 2 的 n 次幂。
int main(void) {
// 0000 1010
int a = 10;
// 0001 0100
printf("%d\n", a<<1); // 20
// 0010 1000
printf("%d\n", a<<2); // 40
return 0;
}
右移 >>
右移运算符 >>
将其左侧的操作数的值每位向右移动,移动的位数由其右侧的操作数指定。丢弃移出左侧操作数有段的位。对于 unsigned 类型,使用 0 填充左端空出的位。对于有符号类型,结果依赖于机器。空出的位可能用 0 填充,或者使用符号(最左端) 位的副本填充。右移 n 次等价于除以 2 的 n 次幂。
数据类型转换#
- 数据有不同的类型,不同类型数据之间进行混合运算时必然涉及到类型的转换问题。
- 转换的方法有 2 种:
- 自动转换(隐式转换):遵循一定的规则,由编译系统自动完成。
- 强制类型转换:把表达式的运算结果强制转换成所需的数据类型。
- 类型转换的原则:占用内存字节数少(值域小) s的类型,向占用内存字节数多(值域大) 的类型转换,以保证精度不降低。
简单的位运算#
打开位#
- flag = 10011010,将位 2 打开
flag | 00000100 (10011010) |(00000100) =(10011110)
- 将所有位打开
flag | ~flag (10011010) |(01100101) =(11111111)
关闭位#
flag & ~flag
(10011010)
&(01100101)
=(00000000)
转置位#
转置(toggling) 一个位表示如果该位打开,则关闭该位;如果该位关闭,则打开。您可以使用位异或运算符来转置。其思想是如果 b 是一个位(1 或 0),那么如果 b 为 1,则 b^1 为 0;如果 b 为 0,则 b^1 为 1。无论 b 的值是 0 还是 1,0^b 为 b。
(10010011)
^(11111111)
=(01101100)
交换两个数#
int a = 6; // 0000 0110
int b = 7; // 0000 0111
a = a^b; // 0000 0001
b = a^b; // 0000 0110
a = a^b; // 0000 0111
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?