
c基础
数据类型
数据类型:c语言中数据类型有3种,分别是基本数据类型、构造数据类型、指针数据类型。

| 打印格式 | 对应数据类型 | 含义 |
|---|---|---|
| %c | char | 字符型,输入的数字按照ASCII码相应转换为对应的字符 |
| %hd | short int | 短整数 |
| %hu | unsigned short | 无符号短整数 |
| %d | int | 接受整数值并将它表示为有符号的十进制整数 |
| %u | unsigned int | 无符号10进制整数 |
| %ld | long | 接受长整数值并将它表示为有符号的十进制整数 |
| %f | float | 单精度浮点数 |
| %lf | double | 双精度浮点数 |
| %e,%E | double | 科学计数法表示的数,此处"e"的大小写代表在输出时用的"e"的大小写 |
| %s | char * | 字符串。输出字符串中的字符直至字符串中的空字符(字符串以'\0‘结尾,这个'\0'即空字符) |
| %p | void * | 以16进制形式输出指针 |
| %o | unsigned int | 无符号8进制整数 |
| %x,%X | unsigned int | 无符号16进制整数,x对应的是abcdef,X对应的是ABCDEF |
示例代码
c
#include <stdio.h>
int main() {
// 1. 整数类型
int integer = 123;
printf("整数(int):%d\n", integer);
// 2. 短整数类型
short short_num = 321;
printf("短整数(short):%hd\n", short_num);
// 3. 长整数类型
long long_num = 123456L;
printf("长整数(long):%ld\n", long_num);
// 4. 长长整数类型
long long ll_num = 123456789LL;
printf("长长整数(long long):%lld\n", ll_num);
// 5. 无符号整数类型
unsigned int uinteger = 456;
printf("无符号整数(unsigned int):%u\n", uinteger);
// 6. 浮点类型(单精度)
float height = 1.77f;
printf("浮点数(float):%f\n", height);
printf("浮点数(科学计数法):%e\n", height);
// 7. 双精度浮点类型
double pi = 3.1415926535;
printf("双精度浮点数(double):%lf\n", pi);
printf("双精度浮点数(科学计数法):%le\n", pi);
// 8. 字符类型
char ch = 'A';
printf("字符(char):%c\n", ch);
printf("字符ASCII码:%d\n", ch);
// 9. 字符串类型
char str[] = "Hello C";
printf("字符串(string):%s\n", str);
// 10. 指针类型
int *ptr = &integer;
printf("指针地址(pointer):%p\n", ptr);
// 11. 十六进制和八进制
int num = 255;
printf("十进制:%d\n", num);
printf("十六进制(小写):%x\n", num);
printf("十六进制(大写):%X\n", num);
printf("八进制:%o\n", num);
// 12. 科学计数法
double sci_num = 123.456;
printf("科学计数法:%e\n", sci_num);
// 13. 格式控制示例
double precise_num = 3.14159;
printf("保留2位小数:%.2f\n", precise_num);
printf("宽度控制(10位右对齐):%10d\n", integer);
printf("宽度控制(左对齐):%-10d\n", integer);
printf("补零显示:%05d\n", integer);
return 0;
}结果
text
整数(int):123
短整数(short):321
长整数(long):123456
长长整数(long long):123456789
无符号整数(unsigned int):456
浮点数(float):1.770000
浮点数(科学计数法):1.770000e+00
双精度浮点数(double):3.141593
双精度浮点数(科学计数法):3.141593e+00
字符(char):A
字符ASCII码:65
字符串(string):Hello C
指针地址(pointer):000000fb021ffc64
十进制:255
十六进制(小写):ff
十六进制(大写):FF
八进制:377
科学计数法:1.234560e+02
保留2位小数:3.14
宽度控制(10位右对齐): 123
宽度控制(左对齐):123
补零显示:00123系统变量
text
#include <stdio.h>
#include <float.h>
#include <limits.h>
int main() {
printf("========== 整数类型限制 ==========\n");
// char类型
printf("char类型位数:%d 位\n", CHAR_BIT);
printf("char最小值:%d\n", CHAR_MIN);
printf("char最大值:%d\n", CHAR_MAX);
printf("signed char最小值:%d\n", SCHAR_MIN);
printf("signed char最大值:%d\n", SCHAR_MAX);
printf("unsigned char最大值:%d\n\n", UCHAR_MAX);
// short类型
printf("short最小值:%d\n", SHRT_MIN);
printf("short最大值:%d\n", SHRT_MAX);
printf("unsigned short最大值:%u\n\n", USHRT_MAX);
// int类型
printf("int最小值:%d\n", INT_MIN);
printf("int最大值:%d\n", INT_MAX);
printf("unsigned int最大值:%u\n\n", UINT_MAX);
// long类型
printf("long最小值:%ld\n", LONG_MIN);
printf("long最大值:%ld\n", LONG_MAX);
printf("unsigned long最大值:%lu\n\n", ULONG_MAX);
// long long类型(如果支持)
#ifdef LLONG_MIN
printf("long long最小值:%lld\n", LLONG_MIN);
printf("long long最大值:%lld\n", LLONG_MAX);
printf("unsigned long long最大值:%llu\n\n", ULLONG_MAX);
#endif
printf("========== 浮点类型限制 ==========\n");
// float类型
printf("float最小值:%e\n", FLT_MIN);
printf("float最大值:%e\n", FLT_MAX);
printf("float精度(有效位数):%d 位\n", FLT_DIG);
printf("float最小精度:%e\n\n", FLT_EPSILON);
// double类型
printf("double最小值:%e\n", DBL_MIN);
printf("double最大值:%e\n", DBL_MAX);
printf("double精度(有效位数):%d 位\n", DBL_DIG);
printf("double最小精度:%e\n\n", DBL_EPSILON);
// long double类型
printf("long double最小值:%Le\n", LDBL_MIN);
printf("long double最大值:%Le\n", LDBL_MAX);
printf("long double精度(有效位数):%d 位\n", LDBL_DIG);
printf("long double最小精度:%Le\n\n", LDBL_EPSILON);
printf("========== 其他限制 ==========\n");
// 浮点数相关
printf("float指数最小值:%d\n", FLT_MIN_EXP);
printf("float指数最大值:%d\n", FLT_MAX_EXP);
printf("float小数位数:%d\n", FLT_MANT_DIG);
return 0;
}结果
text
========== 整数类型限制 ==========
char类型位数:8 位
char最小值:-128
char最大值:127
signed char最小值:-128
signed char最大值:127
unsigned char最大值:255
short最小值:-32768
short最大值:32767
unsigned short最大值:65535
int最小值:-2147483648
int最大值:2147483647
unsigned int最大值:4294967295
long最小值:-2147483648
long最大值:2147483647
unsigned long最大值:4294967295
long long最小值:-9223372036854775808
long long最大值:9223372036854775807
unsigned long long最大值:18446744073709551615
========== 浮点类型限制 ==========
float最小值:1.175494e-38
float最大值:3.402823e+38
float精度(有效位数):6 位
float最小精度:1.192093e-07
double最小值:2.225074e-308
double最大值:1.797693e+308
double精度(有效位数):15 位
double最小精度:2.220446e-16
long double最小值:3.362103e-4932
long double最大值:1.189731e+4932
long double精度(有效位数):18 位
long double最小精度:1.084202e-19
========== 其他限制 ==========
float指数最小值:-125
float指数最大值:128
float小数位数:24位运算符
常见的位运算符号有&、|、^、~、>>、<<,分别代表着如下含义:
| 运算符 | 术语 | 示例 | 结果 |
|---|---|---|---|
| & | 按位与运算 | 011 & 101 | 2个都为1才为1,结果为001 |
| | | 按位或运算 | 011 | 101 | 有1个为1就为1,结果为111 |
| ^ | 按位异或运算 | 011 ^ 101 | 不同的为1,结果为110 |
| ~ | 取反运算 | ~011 | 100 |
| << | 左移运算 | 1010 << 1 | 10100 |
| >> | 右移运算 | 1010 >> 1 | 0101 |
| ps:取反、左右位移运算需要在补码的基础上运算。 |
& (与运算)
按位与(&)运算:位与位进行比较,如果都为1,则为1,否则为0;
text
/**
* 按位与(&)运算:位与位进行比较,如果都为1,则为1,否则为0;
* 示例:
* 40 & 15 = 8
* 0010 1000
* & 0000 1111
* -------------------
* 0000 1000
*/
printf("40 & 15 = %d\n", 40 & 15);| (或运算)
按位或(|)运算:位与位进行比较,如果都为0,则为0,否则全为1;
text
/**
* 按位或(|)运算:位与位进行比较,如果都为0,则为0,否则为1;
* 示例:
* 40 | 15 = 47
* 0010 1000
* | 0000 1111
* ----------------
* 0010 1111
*/
printf("40 | 15 = %d\n", 40 | 15);^ (异或运算)
按位异或运算:位与位进行比较,不同为1,相同为0;
text
/**
* 按位异或运算:位与位进行比较,相同为0,不同为1;
* 示例:
* 40 ^ 15 = 39
* 0010 1000
* ^ 0000 1111
* ------------------
* 0010 0111
*/
printf("40 ^ 15 = %d\n", 40 ^ 15);~ (取反运算)
按位取反运算:补码取反,再将取反后的补码转为原码;
ps:无符号的数据,取反后最高位为1,也不需要逆运算。
text
/**
* 按位取反运算:补码取反,再将取反后的补码转为原码。
* 1、正数取反:由于正数的原码和补码是相同的,取反的方式简便了些。
* 补码(原码) -> 取反 -> 补码逆运算 -> 反码逆运算(符号位不变) -> 取反后的原码
* 2、负数取反:
* 原码 -> 反码 -> 补码 -> 取反 -> 取反后的补码即原码
* 示例:
* 原码(补码) 取反的补码 补码逆运算-1 反码逆运算
* ~40 = 0010 1000 -> 1101 0111 -> 1101 0110 -> 1010 1001 = -41
*
* 原码(补码) 取反的补码 补码逆运算-1 反码逆运算
* ~15 = 0000 1111 -> 1111 0000 -> 1110 1111 -> 1001 0000 = -16
*
* 原码 反码 补码 取反
* ~-15 = 1000 1111 -> 1111 0000 -> 1111 0001 -> 0000 1110 = 14
*/
printf("~40 = %d\n", ~40);
printf("~15 = %d\n", ~15);
printf("~-15 = %d\n", ~(-15));<< (左移运算符)
将数字的二进制补码全部向左移动,空出来的位置补0,超出范围的二进制数丢弃;
有符号的数据左移后最高位如果为1,则需要进行逆运算;
注意事项:
- 无符号的数据,左移后最高位为1,也不需要逆运算;
- -128:1000 0000 特殊情况也不需要逆运算;
text
/**
* 示例:
* 40 << 4 = 0010 1000 << 4 = 1000 0000 = -128 (特殊的不需要逆运算)
* 41 << 4 = 0010 1001 << 4 = 1001 0000 = 1000 1111 = 1111 0000 = -112
* 7 6 5 4 3 2 1 0
* 1 0 0 1 0 0 0 0
*/
int8_t p = 40;
p <<= 4; // p = p << 4;
printf("40 << 4 = %d\n", p);>> (右移运算符)
将数字的二进制补码全部向右移动,空出来的位置补什么,取决于原来的最高位是什么。原来的最高是1就补1, 原来的最高位是0 就补0 。也可以转化成这样的一句话: 正数补0, 负数补1;
text
/*
23:
0001 0111【原码】
0001 0111【反码】
0001 0111【补码】 >> 2
-----------------
0000 0101【补码】 ---> 5
*/
printf(" 23 >> 2 = %d \n" , 23 >> 2) ;
/*
-23:
1001 0111【原码】
1110 1000【反码】
1110 1001【补码】 >> 2
-----------------------------------------------
1111 1010【补码】 -> 1111 1001【反码】-> 1000 0110 【原码】 ==> -6
*/
printf(" -23 >> 2 = %d \n" , -23 >> 2) ;示例代码:
text
#include <stdio.h>
#include <inttypes.h>
int main() {
uint8_t a = 3; // 0000 0011
uint8_t b = 10; // 0000 1010
// 打印显示2个字符,个数不够,左边补0
printf("%02x\n", a & b); // 0000 0010,16进制为02
printf("%02x\n", a | b); // 0000 1011,16进制为0b
printf("%02x\n", a ^ b); // 0000 1001,16进制为09
uint8_t c = 10; // 0000 1010
uint8_t temp = ~c; // 1111 0101
printf("%02x\n", temp); // 1111 0101,16进制为f5
printf("%02x\n", c << 1); // 0001 0100,16进制为14
printf("%02x\n", c >> 1); // 0000 0101,16进制为05
return 0;
}运行结果:
text
02
0b
09
f5
14
05条件分支
if...else
text
#include <stdio.h>
int main() {
// 定义一个整数变量记录年龄
int age;
printf("请输入年龄:");
scanf("%d", &age);
// 判断是否满 18 岁 (>=)
if (age >= 18) {
// 如果满 18 岁,允许进网吧嗨皮
printf("允许进网吧嗨皮\n");
} else {
// 否则,提示回家写作业
printf("回家写作业\n");
}
return 0;
}switch
text
#include <stdio.h>
int main() {
// 1. 定义变量保存数据
int i;
// 2. 输入数据
printf("请输入1~7的数字:");
scanf("%d", &i);
// 3. 使用switch根据数据不同输出不同的结果
switch (i) {
case 1:
printf("Monday\n");
break;
case 2:
printf("Tuesday\n");
break;
case 3:
printf("Wednesday\n");
break;
case 4:
printf("Thursday\n");
break;
case 5:
printf("Friday\n");
break;
case 6:
printf("Saturday\n");
break;
case 7:
printf("Sunday\n");
break;
default:
printf("error\n");
}
return 0;
}循环语句
while
text
#include <stdio.h>
int main() {
// 需求跑步5圈
// 1. 条件变量的定义
int i = 1;
// 2. while 控制重复的次数
while (i <= 5) {
// 3. 打印跑步第几圈
printf("跑步第 %d 圈\n", i);
// 4. 条件改变
i++;
}
return 0;
}do...while语句
text
#include <stdio.h>
int main() {
// 需求跑步5圈
// 1. 条件变量的定义
int i = 1;
do {
// 2.1 打印跑步第几圈
printf("跑步第 %d 圈\n", i);
// 2.2 条件改变
i++;
} while ( i <= 5 ); // 3. 控制重复的次数
return 0;
}for语句
text
#include <stdio.h>
int main() {
// 需求跑步5圈
for (int i = 1; i <= 5; i++) {
printf("跑步第 %d 圈\n", i);
}
return 0;
}跳转关键字
break
text
#include <stdio.h>
int main() {
// 需求: 一共吃5碗饭, 吃到第3碗吃饱了, 结束吃饭动作
// 1. 定义条件变量,为了查看方便, 计数器从 1 开始
int i = 1;
while (i <= 5) { // 2. 控制条件
if (i == 3) {
printf("吃饱了,不吃了\n");
break; // 结束循环,退出循环
}
printf("吃第 %d 碗饭\n", i);
// 3. 条件变量改变
i++;
}
return 0;
}continue
text
#include <stdio.h>
int main() {
// 需求: 一共吃5个苹果,吃到第3个遇到虫子,这个跳过不吃,下一个继续
// 1. 定义条件变量,为了查看方便, 计数器从 1 开始
int i = 1;
while (i <= 5) { // 2. 控制条件
if (i == 3) {
printf("这个有虫子,不吃了\n");
i++; // continue 之前一定要修改计数器(条件变量),否则,导致死循环
continue;; // 跳过本次循环,下次继续
}
printf("吃第 %d 个苹果\n", i);
// 3. 条件变量改变
i++;
}
return 0;
}goto
text
#include <stdio.h>
int main() {
int i = 0;
while (i < 3) {
if(i == 1) {
goto End; // 跳转到End标签
}
printf("i = %d\n", i);
i++;
}
End:
printf("this is ending!\n");
return 0;
}
