C语言最早是在1972年由贝尔实验室的丹尼斯·里奇(Dennis Ritch)和肯·汤普逊(KenThompson)在开发UNIX操作系统时设计了C语言。现如今成为广受欢迎的编程语言之一.
定义程序的目标
设计程序
编写代码
编译
运行程序
测试和调试程序
c#include<stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
程序分析:
c++#include<stdio.h> //调用C语言标准库,为main()中调用的printf()函数提供函数原型
Cint main(){} //C语言入口函数,程序的运行将从这里开始
cprintf("hello world\n");//控制台打印函数,将指定内容打印到屏幕上,"\n"转义字符,打印一个回车
creturn 0; //main()函数返回值,在main()结束时返回一个整数类型值
graph TB
subgraph 1
a1["main()"]-->a2["printf(hello world);"]-->a3["return 0;"]
end
subgraph 2
stdio.h-->printf
end
注:标准输入输出函数包括printf(),scanf()等函数
c//使用printf()函数
//打印输出整数型变量
int i= 0;
printf("%d\n",i);/*函数的第一个参数为转换说明和转义字符,%d表示正要打印的是一个整数型变量,\n则表示会输出一个回车;第二个参数是要输出的变量名,printf()函数可以输出多个变量的值,将要输出的变量加在第二,第三....个参数上*/
c//使用scanf()函数
//读入一个字符
char ch;
scanf("%c",&ch); //scanf()函数的参数意义与printf()基本一致,也可以同时读入多个变量
一个完整的C语言程序,是由一个、且只能有一个main()
函数(又称主函数,必须有)和若干个其他函数结合而成(可选)
main
函数是程序的入口,即程序从main
函数开始执行main
函数前声明,在main
函数或者其他函数中调用C语言中内置的关键字
char
、short
、int
、long
、float
、double
、
struct
、union
、enum
、signed
、unsigned
、void
这些关键字是用于定义变量或者类型的关键字,在后面的章节会讲到
register
、static
、const
、auto
、extern
register
是寄存器的意思,用register
修饰的变量是寄存器变量,
即:在编译的时候告诉编译器这个变量是寄存器变量,尽量将其存储空间分配在寄存器中
注意:
register
只能修饰字符型及整型的,不能修饰浮点型register
修饰的变量可能存放在寄存器中不存放在内存中,所以不能对寄存器变量取地址。因为只有存放在内存中的数据才有地址static
是静态的意思,使用static
修饰全局变量、局部变量、函数。可以提升生命周期const
是常量的意思。使用const
修饰,变量就不可以修改了auto
是自动判断变量类型的关键字,在C++中比较常用extern
是外部的意思,一般用于函数和全局变量的声明,可以使函数和变量在文件外被访问if
、else
、break
、continue
、for
、while
、do
、switch
、case
、goto
、default
这些关键字是用于控制分支循环结构的关键字,在后面的章节会讲到
sizeof
、typedef
、volatile
sizeof
用来测试变量、数组的占用储存空间的大小
typedef
重命名,作用是给一个已有的类型,重新起一个类型名
c//给short关键字取一个别名
typedef short INT16; //将short关键字修改为INT16,在后面的变量声明中可以使用INT16替代short关键字
volatile
是易改变的意思,用voltile
定义的变量,是易改变的,即告诉CPU每次用volatile
的时候,重新去内存中取,保证用的是最新的值,而不是寄存器中的备份cvolatile int a = 10;
注意:
变量的命名规则:
命名风格:
stu_num
StuNum
int Num;
int num;
C语言的数据类型简单的划分可以是
C语言中储存数据的量简单的划分可以是
**常量:**在程序运行中,不可改变值的量
'a'
、'\t'
"sdafsf"
1
、2313
、0x3f2a
"a\0"
;而使用单引号则是'a'
,多一个\0
也是字符和字符串的区别,是由编译器自动添加的**变量:**在程序运行中,可以改变值的量
类型 | 描述 |
---|---|
int | 整型(in t)是储存整数的一种数据类型,在内存中占用4个字节,数据范围: -2,147,483,648 |
char | 字符型(char )是容纳单字符的一种数据类型,占用1个字节,数据范围为-128 ~ +127(-2^7~2^7-1) |
float | 浮点数型(float )是用于存储单精度浮点数的一种数据类型,占用4个字节,至少精确表示小数点后的6位有效 数字 |
double | 浮点数型(double )是用于存储双精度浮点型的一种数据类型,占用8个字节,至少精确表示小数点后13 位有效数字 |
long long | 长长整型(int )是储存整数的一种数据类型,在内存中占用8个字节,数据范围:-9223372036854775808 |
数据类型 | 描述 |
---|---|
void | 空类型 |
long | 长整数型 |
short | 短整数型 |
unsigned | 无符号整数型 |
signed | 有符号型 |
Bool | 布尔型 |
Complex | 复数类型 |
Imaginary | 虚数型 |
注意:
void
不能定义变量,没有void
类型的变量void
用来修饰函数的参数或返回值,代表函数没有参数或者返回值代码演示:
c//初始化并打印整数变量
#include<stdio.h>
int main()
{
int x=2;
int y=2.1;
printf("%d\n",x);
printf("%d\n",y);
}
输出结果: 2 2
c//初始化并打印整数和浮点数变量
#include<stdio.h>
int main()
{
int x=2;
float y=2.1;
printf("%d\n",x);
printf("%f\n",y);
}
输出结果: 2 2.100000
c//控制输出浮点数位数
#include<stdio.h>
int main()
{
int x=2;
float y=2.1;
printf("%d\n",x);
printf("%.1f\n",y);
}
输出结果: 2 2.1
c//初始化字符型变量并打印
#include<stdio.h>
int main()
{
char c='a';
printf("%c\n",c);
}
输出结果: a
int
在有的编译器为16位
有的为32位
32位
系统中,指针的占用空间为4字节
;而在64位
中,指针的占用空间为8字节
。(直接影响就是32位系统只能使用最大4G的内存,而64位系统可以使用4×4294967296G的内存)概念:
由若干个相同或不同类型数据构成的集合,这种数据类型被称为构造类型例: int a[10];
数组、结构体、共用体、枚举
数据有不同的类型,不同类型数据之间进行混合运算时必然涉及到类型的转换问题.
转换的方法有两种:
遵循一定的规则,由编译系统自动完成.
把表达式的运算结果强制转换成所需的数据类型
自动转换的原则:
占用内存字节数少(值域小)的类型,向占用内存字节数多(值域大)的类型转换,以保证精度不降低.
转换方向:
graph BT
字节数少-->字节数多
a1["signed int"]-->a2["unsigned int"]-->a3["long"]-->a4["double"]
a5["float"]-->a4
b1["char,short"]-->a1
char
、short int
、int
类型中的一种或者多种,没有其他类型了参加运算的成员全部变成int
类型的参加运算,结果也是int
类型的c10/3 //没有其他类型参与,结果为int类型,即3
double
类型的参加运算,结果也是 double
型c10/3.0 //有浮点数参与,结果为float类型,即3.3333...
**强制转换:**通过类型转换运算来实现
语法:(类型说明符)(表达式)
功能:
例如:
(float)a;
把a的值转换为实型(int)(x+y);
把x+y 的结果值转换为整型注意:
使用scanf
或者printf
输入输出数据时,需要根据数据类型指定不同的转换说明,3.1中是主要的转换说明
转换说明:
转换说明 | 输出 |
---|---|
%a | 浮点数、十六进制数和p记数法(C99/C11) |
%A | 浮点数、十六进制数和p记数法(C99/C11) |
%c | 单个字符 |
%d | 有符号十进制整数 |
%e | 浮点数,e记数法 |
%E | 浮点数,E记数法 |
%f | 浮点数,十进制记数法 |
%g | 根据值的不同,自动选择%f 或%e 。%e 格式用于指数小于-4或者大于或等于精度时 |
%G | 根据值的不同,自动选择%f 或%E 。%E 格式用于指数小于-4或者大于或等于精度时 |
%i | 有符号十进制整数(与%d 相同) |
%o | 无符号八进制整数 |
%p | 指针 |
%s | 字符串 |
%u | 无符号十进制整数 |
%x | 无符号十六进制整数,使用十六进制数0f |
%X | 无符号十六进制整数,使用十六进制数0F |
%% | 打印一个百分号 |
代码演示:
cchar ch='h';
printf("%c",ch);
输出结果: h
cfloat i=1.222;
printf("%f",i);
输出结果: 1.222000
c//打印输出变量i的地址,运行机器为64位
int i=10;
int* p=&i;
printf("%p",p);
输出结果: 000000BF51CFF834
c//打印一个百分号
printf("%%");
输出结果: %
关于输入转换说明:
代码演示:
c//读入一个整数型变量
int i=10;
scanf("%d",&i);
修饰符 | 含义 |
---|---|
标记 | 描述了5种标记(-、+、空格、#和0),可以不使用标记或使用多个标记。 示例: "%-10d" |
数字 | 最小字段宽度。 如果该字段不能容纳待打印的数字或字符串,系统会使用更宽的字段示例: "%4d" |
.数字 | 精度。对于%e 、%E 和%f 转换,表示小数点右边数字的位数对于%g 和%G 转换,表示有效数字最大位数对于 %s 转换,表示待打印字符的最大数量对于整型转换,表示待打印数字的最小位数如有必要,使用前导0来达到这个位数 只使用.表示其后跟随一个0,所以 %.f 和%.0f 相同示例: "%5.2f" 打印一个浮点数,字段宽度为5字符,其中小数点后有两位数字 |
h | 和整型转换说明一起使用,表示short int 或unsigned short int 类型的值示例: "%hu" 、"%hx" 、"%6.4hd" |
hh | 和整型转换说明一起使用,表示signed char 或unsigned char 类型的值示例: "%hhu" 、 "%hhx" 、"%6.4hhd" |
j | 和整型转换说明一起使用,表示intmax_t 或uintmax_t 类型的值。这些类型定义在stdint.h 中示例: "%jd" 、"%8jx" |
l | 和整型转换说明一起使用,表示long int 或unsigned long int 类型的值示例: "%ld" 、"%8lu" |
ll | 和整型转换说明一起使用,表示long long int 或unsigned long long int 类型的值(C99)示例: "%lld" 、"%8llu" |
L | 和浮点转换说明一起使用,表示long double 类型的值示例: "%Ld" 、"%10.4Le" |
t | 和整型转换说明一起使用,表示ptrdiff t 类型的值。ptrdiff_t 是两个指针差值的类型(C99)示例: "%td" 、"%12ti" |
z | 和整型转换说明一起使用,表示size t 类型的值。size t 是sizeof 返回的类型(C99)示例: "%zd" 、"%12zd" |
代码演示:
注:转换说明修饰符在格式化输出方面有很大的作用
c//控制输出小数位数
float pi=3.1415926;
printf("%.4f",pi);
输出结果: 3.1416
c//控制输出占格数
float pi = 3.1415926;
printf("%10.4f", pi); //此时输出占位为10位,除去显示的位数,前面空出四个空位
printf("%-10.4f", pi); //"-"为向左对齐,此时输出占位为10位,除去显示的位数,后面空出四个空位
输出结果: 3.1416 3.1416
c//输出无符号和长整数型变量
unsigned int ui = 10;
long long int i = 100000000000000000;
printf("%u\n", ui);
printf("%lld\n", i);
输出结果: 10 100000000000000000
c//输出sizeof()函数的返回值
int i = 10;
printf("%zd",sizeof(i));
输出结果: 4
转义序列 | 含义 |
---|---|
\a | 警报(ANSI C) |
\b | 退格 |
\f | 换页 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ \ | 反斜杠( \ ) |
\ ' | 单引号 |
\ " | 双引号 |
\ ? | 问号 |
\0oo | 八进制值(oo 必须是有效的八进制数,即每个o可表示0~7中的一个数) |
\xhh | 十六进制值(hh 必须是有效的十六进制数,即每个h可表示0~f中的一个数) |
ASCII
(American Standard Code for Information Interchange,美国信息互换标准代码)是一套基于拉丁字母的字符编码,共收录了 128 个字符,用一个字节就可以存储,它等同于国际标准 ISO/IEC 646
ASCII
编码于 1967 年第一次发布,最后一次更新是在 1986 年,迄今为止共收录了 128 个字符,包含了基本的拉丁字母(英文字母)、阿拉伯数字(也就是 1234567890)、标点符号(,.!等)、特殊符号(@#$%^&等)以及一些具有控制功能的字符(往往不会显示出来)
ASCII编码对照表:
二进制 | 十进制 | 十六进制 | 字符/缩写 | 解释 |
---|---|---|---|---|
00000000 | 0 | 00 | NUL (NULL) | 空字符 |
00000001 | 1 | 01 | SOH (Start Of Headling) | 标题开始 |
00000010 | 2 | 02 | STX (Start Of Text) | 正文开始 |
00000011 | 3 | 03 | ETX (End Of Text) | 正文结束 |
00000100 | 4 | 04 | EOT (End Of Transmission) | 传输结束 |
00000101 | 5 | 05 | ENQ (Enquiry) | 请求 |
00000110 | 6 | 06 | ACK (Acknowledge) | 回应/响应/收到通知 |
00000111 | 7 | 07 | BEL (Bell) | 响铃 |
00001000 | 8 | 08 | BS (Backspace) | 退格 |
00001001 | 9 | 09 | HT (Horizontal Tab) | 水平制表符 |
00001010 | 10 | 0A | LF/NL(Line Feed/New Line) | 换行键 |
00001011 | 11 | 0B | VT (Vertical Tab) | 垂直制表符 |
00001100 | 12 | 0C | FF/NP (Form Feed/New Page) | 换页键 |
00001101 | 13 | 0D | CR (Carriage Return) | 回车键 |
00001110 | 14 | 0E | SO (Shift Out) | 不用切换 |
00001111 | 15 | 0F | SI (Shift In) | 启用切换 |
00010000 | 16 | 10 | DLE (Data Link Escape) | 数据链路转义 |
00010001 | 17 | 11 | DC1/XON (Device Control 1/Transmission On) | 设备控制1/传输开始 |
00010010 | 18 | 12 | DC2 (Device Control 2) | 设备控制2 |
00010011 | 19 | 13 | DC3/XOFF (Device Control 3/Transmission Off) | 设备控制3/传输中断 |
00010100 | 20 | 14 | DC4 (Device Control 4) | 设备控制4 |
00010101 | 21 | 15 | NAK (Negative Acknowledge) | 无响应/非正常响应/拒绝接收 |
00010110 | 22 | 16 | SYN (Synchronous Idle) | 同步空闲 |
00010111 | 23 | 17 | ETB (End of Transmission Block) | 传输块结束/块传输终止 |
00011000 | 24 | 18 | CAN (Cancel) | 取消 |
00011001 | 25 | 19 | EM (End of Medium) | 已到介质末端/介质存储已满/介质中断 |
00011010 | 26 | 1A | SUB (Substitute) | 替补/替换 |
00011011 | 27 | 1B | ESC (Escape) | 逃离/取消 |
00011100 | 28 | 1C | FS (File Separator) | 文件分割符 |
00011101 | 29 | 1D | GS (Group Separator) | 组分隔符/分组符 |
00011110 | 30 | 1E | RS (Record Separator) | 记录分离符 |
00011111 | 31 | 1F | US (Unit Separator) | 单元分隔符 |
00100000 | 32 | 20 | (Space) | 空格 |
00100001 | 33 | 21 | ! | |
00100010 | 34 | 22 | " | |
00100011 | 35 | 23 | # | |
00100100 | 36 | 24 | $ | |
00100101 | 37 | 25 | % | |
00100110 | 38 | 26 | & | |
00100111 | 39 | 27 | ' | |
00101000 | 40 | 28 | ( | |
00101001 | 41 | 29 | ) | |
00101010 | 42 | 2A | * | |
00101011 | 43 | 2B | + | |
00101100 | 44 | 2C | , | |
00101101 | 45 | 2D | - | |
00101110 | 46 | 2E | . | |
00101111 | 47 | 2F | / | |
00110000 | 48 | 30 | 0 | |
00110001 | 49 | 31 | 1 | |
00110010 | 50 | 32 | 2 | |
00110011 | 51 | 33 | 3 | |
00110100 | 52 | 34 | 4 | |
00110101 | 53 | 35 | 5 | |
00110110 | 54 | 36 | 6 | |
00110111 | 55 | 37 | 7 | |
00111000 | 56 | 38 | 8 | |
00111001 | 57 | 39 | 9 | |
00111010 | 58 | 3A | : | |
00111011 | 59 | 3B | ; | |
00111100 | 60 | 3C | < | |
00111101 | 61 | 3D | = | |
00111110 | 62 | 3E | > | |
00111111 | 63 | 3F | ? | |
01000000 | 64 | 40 | @ | |
01000001 | 65 | 41 | A | |
01000010 | 66 | 42 | B | |
01000011 | 67 | 43 | C | |
01000100 | 68 | 44 | D | |
01000101 | 69 | 45 | E | |
01000110 | 70 | 46 | F | |
01000111 | 71 | 47 | G | |
01001000 | 72 | 48 | H | |
01001001 | 73 | 49 | I | |
01001010 | 74 | 4A | J | |
01001011 | 75 | 4B | K | |
01001100 | 76 | 4C | L | |
01001101 | 77 | 4D | M | |
01001110 | 78 | 4E | N | |
01001111 | 79 | 4F | O | |
01010000 | 80 | 50 | P | |
01010001 | 81 | 51 | Q | |
01010010 | 82 | 52 | R | |
01010011 | 83 | 53 | S | |
01010100 | 84 | 54 | T | |
01010101 | 85 | 55 | U | |
01010110 | 86 | 56 | V | |
01010111 | 87 | 57 | W | |
01011000 | 88 | 58 | X | |
01011001 | 89 | 59 | Y | |
01011010 | 90 | 5A | Z | |
01011011 | 91 | 5B | [ | |
01011100 | 92 | 5C | \ | |
01011101 | 93 | 5D | ] | |
01011110 | 94 | 5E | ^ | |
01011111 | 95 | 5F | _ | |
01100000 | 96 | 60 | ` | |
01100001 | 97 | 61 | a | |
01100010 | 98 | 62 | b | |
01100011 | 99 | 63 | c | |
01100100 | 100 | 64 | d | |
01100101 | 101 | 65 | e | |
01100110 | 102 | 66 | f | |
01100111 | 103 | 67 | g | |
01101000 | 104 | 68 | h | |
01101001 | 105 | 69 | i | |
01101010 | 106 | 6A | j | |
01101011 | 107 | 6B | k | |
01101100 | 108 | 6C | l | |
01101101 | 109 | 6D | m | |
01101110 | 110 | 6E | n | |
01101111 | 111 | 6F | o | |
01110000 | 112 | 70 | p | |
01110001 | 113 | 71 | q | |
01110010 | 114 | 72 | r | |
01110011 | 115 | 73 | s | |
01110100 | 116 | 74 | t | |
01110101 | 117 | 75 | u | |
01110110 | 118 | 76 | v | |
01110111 | 119 | 77 | w | |
01111000 | 120 | 78 | x | |
01111001 | 121 | 79 | y | |
01111010 | 122 | 7A | z | |
01111011 | 123 | 7B | { | |
01111100 | 124 | 7C | | | |
01111101 | 125 | 7D | } | |
01111110 | 126 | 7E | ~ | |
01111111 | 127 | 7F | DEL (Delete) | 删除 |
用运算符将运算对象(也称操作数)连接起来的、符合C语法规则的式子,称为C算术表达式运算对象
包括: 常量、变量、函数等
例如:
a * b/c一 1 .5 + 'a'
+
、a+b
++
自增运算符 变量值+1
--
自减运算符 变量值-1int a=10;
a++;
(条件表达式)?(表达式1):(表达式2)
=
、+=
、-=
、*=
、/=
、%=
将一个常量或者变量赋值给一个变量的运算符
+
、-
、*
、/
、 %
注意:
%
为取模运算符;10%3=1
+=
为双目运算符(双元运算符);a+=3;
等价于a=a+3;
;其他以此类推
>
、<
、==
、>=
、<=
、!=
判断数据是否相等时使用==
或!=
注意:
==
而不是赋值运算符=
&&
逻辑与c(a>b)&& (a<c)//两个条件都为真,则结果为真
(b<a<c)//这种表达方式是错误的
||
逻辑或c(a>p)||(a<c) //两个条件至少有一个为真,则结果为真
!
逻辑非c!(a>b) //将(a>b)取反
所谓短路,就是用||,&&,这些双目操作符,实现一些if的判断。
因为这些操作符具有的一个特点是:先计算左边的表达式值,能得到值就不计算右边了,不能再计算右边
c++int x,y,t;
x=y=3;
t=++x||++y;
cout<<x<<" "<<y<<" "<<t<<endl;
4 3 1
功能描述:
~
把1变成0,把0变成1.语法:
~(10011010)
转换为(01100101)
功能描述:
&
通过比较两个运算对象,生成一个新值.对于每个位,只有两个运算对象中相应的位都为1时,结果才为1.语法:
(10010011) & (00111101)
得到(00010001)
功能描述:
|
通过比较两个运算对象,生成一个新值.对于每个位,如果两个运算对象中相应的位为1,结果就为1.语法:
(10010011) | (00111101)
得到(10111111)
功能描述:
^
通过比较两个运算对象.对于每个位,如果两个运算对象中相应的位一个为1,另一个不为1,结果为1.语法:
(10010011) ^ (00111101)
得到(10101110)
功能描述:
语法:
(10001010) << 2
得到(00101000)
功能描述:
语法:
(10001010) >> 2
得到(00100010)
语法:
()?():();
A?B:C;
如果?
前边的表达式成立,整个表达式的值,是?
和:
之间的表达式的结果否则是:
之后的表达式的结果
语法:
(),();
注意
语法:
i++
i--
运算符在变量的后面,在当前表达式中先用i
的值,下条语句的时候i
的值改变
注意:
++i
或者是--i
则是先自增(自减)后,将i
的值赋出去MSVC
(Visual Studio)和minGW
编译器中自增自减的运算顺序可能不同运算符优先级 在表达式中按照优先级先后进行运算,优先级高的先于优先级低的先运算。 优先级一样的按结合性来运算
优先级 | 运算符 | 结合律 |
---|---|---|
1 | 后缀运算符:[] () · -> ++ -- (类型名称){列表} | 从左到右 |
2 | 一元运算符:++ -- ! ~ + - * & sizeof_Alignof | 从右到左 |
3 | 类型转换运算符:(类型名称) | 从右到左 |
4 | 乘除法运算符:* / % | 从左到右 |
5 | 加减法运算符:+ - | 从左到右 |
6 | 移位运算符:<< >> | 从左到右 |
7 | 关系运算符:<<= >>= | 从左到右 |
8 | 相等运算符:== ``!=` | 从左到右 |
9 | 位运算符 AND : & | 从左到右 |
10 | 位运算符 XOR:^ | 从左到右 |
11 | 位运算符 OR:` | ` |
12 | 逻辑运算符 AND:&& | 从左到右 |
13 | 逻辑运算符 OR:` | |
14 | 条件运算符:()?():() | 从右到左 |
15 | 赋值运算符: = += -= *= /= %= &= ^= ` | = <<= >>=` |
16 | 逗号运算符:, | 从左到右 |
运算符的组合方式:
表达式 | 结合律 | 组合方式 |
---|---|---|
a/b%c | 从左到右 | (a/b)%c |
a=b=c | 从右到左 | a=(b=c) |
注意:
()
括起来,括号的优先级最高,优先算括号里的if
,else
语句cif(条件表达式) //条件表达式为真时执行代码块,否则退出if语句
{
代码块
}
if(条件表达式)
{
代码块1
}
else
{
代码块2
}
if(条件表达式)
语句1;
if(条件表达式)
语句1;
else 语句2;
switch
语句cswitch(表达式)//表达式只能是字符型或整型的(short int int long int)
}
case 常量表达式1:
语句1;
break;
case 常量表达式2:
语句2;
break;
default:语句3; break;
}
for
循环语句cfor(初始化计数器;条件表达式;计数器自增表达式)
{
//复合语句,循环体
}
while
循环语句cwhile(条件表达式)
{
//循环体,复合语句
}
//进入while循环的时候,首先会判断条件表达式是否为真,为真进入循环体,否则退出循环
do...while
循环语句cdo{
循环体
}while(条件表达式)
//先执行循环体里的代码,然后去判断条件表达式是否为真,为真再次执行循环体,否则退出循环。
break
和continue
语句
goto
语句
goto
语句会降低代码可读性,且经过验证,goto
语句能实现的代码,C语言中其他语句也能实现。goto
语句源自于汇编语言的jmp
语句,在高级语言中使用不妥数组是若干个相同类型的变量在内存中有序存储的集合
cint a[10];//定义了一个整型的数组a,a是数组的名字,数组中有10个元素,每个元素的类型都是int类型,而且在内存中连续存储。
这十个元素分别是a[0] a[1] .... a[9] a[0]~a[9]在内存中连续的顺序存储
字符数组 即若干个字符变量的集合,数组中的每个元素都是字符型的变量
cchar s[10];
s[0],s[1]...s[9];
短整型的数组
cshort inta[10];
a[0] ,a[9];
a[0]=4;
a[9]=8;
整型的数组
cint a[10];
a[0]a[9];
a[0]=3;
a[0]=6;
长整型的数组
clont int a[5];
浮点型的数组(单、双)
cfloat a[6];
a[4]=3.14f;
double a[8];
a[7]=3.115926;
指针数组
cchar*a[10];
int *a[10];
结构体数组
cstruct stu[10];
语法:
a[x][y][z]...
在此基础上可以多次嵌套常见的嵌套层数:
语法:
c数据类型 数组名 [x][y][z]...
注意:
ca[][3]={{1,2,3},{4,5,6},{7,8,9},{10,11,12}};
定义数组的时候,顺便给数组的元素赋初值,即开辟空间的同时并且给数组元素赋值
全部初始化
cint a[5]={2,4,7,8,5};
代表的意思: a[0]=2; a[1]=4;a[2]=7;a[3] =8;a[4]=5;
部分初始化
cint a[5]={2,4,3};//初始化赋值不够后面补0
//a[0]= 2; a[1]= 4;a[2]=3;a[3]=0;a[4]=0;
注意:
按行初始化:
全部初始化
cint a[2][2]={{1,2},{4,5}};
a[0][0]=1;
a[0][1]=2;
a[1][0]=4;
a[1][1]=5;
部分初始化
cint a[3][3]={{1,2},{1}};
a[0][0]= 1;
a[0][2]= 0;
逐个初始化:
全部初始化:
cint a[2][3]={2,5,4,2,3,4};
部分初始化:
cint a[2][3]={3,5,6,8};
语法:
c数组名[下标];//下标代表数组元素在数组中的位置
语法:
c数组名[行下标][列下标];
cchar c1[]={'c', ' ’ ,'p' , 'r' , ’o’ , 'g'};
cchar c2[] = "c prog";
cchar a[][5]={{'B','A','S','I','C'},{'d','B','A','S','E'}};
cchar a[][6]={"hello","world"};
注意:
'\0';
函数是c语言的功能单位,实现一个功能可以封装一个函数来实现。 定义函数的时候一切以功能为目的,根据功能去定函数的参数和返回值。
void
或什么都不写return
如果没有返回值类型,默认返回整型void
函数的定义即函数的实现
函数的定义方法
c返回值类型 函数名字(形参列表)
{
//函数体,函数的功能在函数体里实现
}
注意:
概念:
主调函数和被调函数在同一个文件中时:
主调函数和被调函数在不同一个文件中时:
extern
函数的调用方法
变量=函数名(实参列表);//带返回值的
函数名(实参列表);//不带返回值的
有无返回值
有无形参
函数名(实参列表);//带形参的
函数名()://没有形参的
注意:
static
修饰。这样的函数被称为内部函数static
限定了函数的作用范围,在定义的.c
中有效。.c
中的函数调用0x00 00 00 00
~0xff ff ff ff
static
修饰),或全局变量,没有初始化的,存在此区概念:
cint num=100;//num就是一个全局变量
int main()
{
return 0;
}
作用范围:
extern int num;
生命周期:
注意:
概念:
static
修饰cstatic int num=100;//num_就是一个静态全局变量
int main()
{
return o;
}
作用范围:
static
限定了静态全局变量的,作用范围只能在它定义的.c(源文件)中有效生命周期:
注意:
概念:
cint main()
{
int num;//局部变量
{
int a;//局部变量
}
}
作用范围:
生命周期:
概念:
static
修饰作用范围:
生命周期:
**指针的作用:**可以通过指针间接访问内存
语法:
数据类型* 变量名;
代码演示:
c++int main()
{
int a = 10;
cout<<"a = "<<a<<endl;
int* p = &a; //&a取址
*p = 100; //*p解引用,获取p指针指向的内存
cout<<"a = "<<a<<endl;
}
使用指针需要用到指针的运算符
&
取地址*
取值(解引用)按照数据类型分类,指针可以为多种数据类型,支持C语言中所有的数据类型
注意:
按照指针的功能分类,可以分为以下几种:
void*
代码演示:
c++//指针所占内存空间
cout<<"sizeof(int*) = "<<sizeof(int*)<<endl;
cout<<"sizeof(float*) = "<<sizeof(float*)<<endl;
cout<<"sizeof(char*) = "<<sizeof(char*)<<endl;
cout<<"sizeof(double*) = "<<sizeof(double*)<<endl;
cout<<"sizeof(long long*) = "<<sizeof(long long*)<<endl;
输出结果: sizeof(int*) = 8 sizeof(float*) = 8 sizeof(char*) = 8 sizeof(double*) = 8 sizeof(long long*) = 8
**空指针:**指针变量指向内存中编号为0的空间 **用途:**初始化指针变量 **注意:**空指针指向的内存是不可以访问的
c++//空指针
int* p=NULL;
//空指针指向的内存是不可以访问的
//0~255之间的内存编号是系统占用的,因此不可以访问
*p = 100;
**野指针:**指针变量指向非法的内存空间
const修饰指针有三种情况:
const
修饰指针--常量指针
const
修饰常量---指针常量
const
既修饰指针,又修饰常量
代码演示:
c++//常量指针
//特点:指针的指向可以修改,但是指针指向的值不可以改
const int* p=&a;
*p = 20; //错误,指针指向的值不可以修改
p = &b; //正确,指针指向可以改
c++//指针常量
//特点:指针的指向不可以改,指针指向的值可以改
int* const p = &a;
*p = 20; //正确,指针指向的值可以改变
*p = &b; //错误,指针的指向不可以改
c++//const既修饰指针,又修饰常量
const int* const p = &a;
*p = 20; //错误,指针指向的值不可以修改
p = &b; //错误,指针的指向不可以修改
**作用:**利用指针访问数组中元素
c++int arr[10] = {2,3,3,1,4,6,4,3,2,1};
int* p = arr; //指向数组第一个元素的指针
for(int i = 0; i<10; i++)
{
cout<<*(p+i)<<endl;; //解引用,取得0~9号元素的值
//相当于 arr[i];
}
输出结果: 2 3 3 1 4 6 4 3 2 1
**作用:**利用指针作函数参数,可以修改实参的值
c++void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int a = 10, b = 20;
cout << "修改前: " << "a = " << a << " b = " << b<< endl;
swap(&a, &b);
cout << "修改后: " << "a = " << a << " b = " << b<< endl;
}
输出结果: 修改前: a = 10 b = 20 修改后: a = 20 b = 10
实现冒泡排序算法函数
代码演示:
c++//冒泡排序函数
void bubble_sort(int* arr,int len)
{
for(int i = 0;i<len-1;i++)
{
for(int j = 0;j<len-i-1;j++)
{
if(arr[j]>arr[j+1])
{
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}
int main()
{
int arr[10] = {2,3,3,1,4,6,4,3,2,1,1};
cout<<"排序前: "<<endl;
for(int i = 0;i<10;i++)cout<<arr[i]<<" ";
cout<<endl;
bubble_sort(arr,10);
cout<<"排序后: "<<endl;
for(int i = 0;i<10;i++)cout<<arr[i]<<" ";
}
输出结果: 排序前: 2 3 3 1 4 6 4 3 2 1 排序后: 1 1 2 2 3 3 3 4 4 6
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
语法:struct结构体名{ 结构体成员列表};
通过结构体创建变量的方式有三种:
struct结构体名变量名
struct结构体名 变量名={成员1值,成员2值...}
定义结构体时顺便创建变量
.c
中的头文件展开、宏展开
生成的文件是.i
文件.i
文件生成.s
汇编文件.s
汇编文件生成.o
目标文件.o
文件链接成目标文件bashgcc -E hello.c -o hello.i
bashgcc -s hello.i -o hello.s
bashgcc -c hello.s -o hello.o
bashgcc hello.o -o hello_elf
简洁命令
bashgcc hello.cpp -o hello.out # 编译
./hello.out # 运行
概念:#include <>
引用的是编译器的类库路径里面的头文件.
VS2022的库文件目录在D:\Windows Kits\10\Include\10.0.19041.0\ucrt
下,#include<stdio.h>
默认在此目录下寻找,一般用于引用标准库文件
概念:#include ""
引用的是项目相对路径中的头文件
c++//头文件位于当前目录
#include "main.h"
c++//头文件位于子目录
#include "header/main.h"
c++//头文件位于父目录
#include "../header/main.h"
注意:
include
经常用来包含头文件,可以包含.c
文件,但是大家不要包含.c
因为include
包含的文件会在预编译被展开,如果一个.c
被包含多次,展开多次,会导致函数重复定义。所以不要包含.c
文件include
等预处理操作进行处理并不会进行语法检查这个阶段有语法错误也不会报错,第二个阶段即编译阶段才进行语法检查定义宏用define
去定义
宏是在预编译的时候进行替换
c#define PI 3.14
//在预编译的时候如果代码中出现了PI 就用3.14去替换
宏的好处:
注意:
c#define S(a,b) a*b
//S(2,4)将来在预处理的时候替换成实参替代字符串的形参,其他字符保留,2*4
注意:
c//形参不加括号
#define S(a,b) a*b
num = S(3+5,7); //预编译时解释为3+5*7
//形参加括号
#define S(a,b) (a)*(b)
num = S(3+5,7); //预编译时解释未(3+5)*(7)
**作用:**防止头文件被重复引用
#ifndef
c++#ifndef _NAME_H_ //_NAME_H_是头文件的名称,此处宏名不可重复使用,不可与项目中其他宏名相同
#define _NAME_H_ //ifndef->if not defined XXX 如果定义则不编译文件
/*****
*头文件
*****/
#endif
注意:
#ifndef
相似的预处理器还有#if
、#ifdef
#if 常量
如果常量为真,则编译下面的代码块,否则不编译#ifdef 常量
如果常量为真,则编译下面的代码块,否则不编译#pragma once
用#pragma once
指令,将其附加到指定头文件的最开头出,则该头文件只会被包含一次
c++#pragma once
/*****
*头文件
*****/
注意:#pragma once
只能作用于某个具体的文件,而无法像#ifndef
那样作用于指定的一段代码。
为了提高程序的可移植性,#pragma once
和 #ifndef
经常被结合使用来避免头文件被重复引用
c++#pragma once
#ifndef _NAME_H_
/*****
*头文件
*****/
#endif
当编译器可以识别#pragma once
时,则整个文件仅被编译一次;反之,即便编译器不识别#pragma once
指令,此时仍有#ifndef
指令发挥作用.
_Pragma
操作符可以看作是#pragma
的增强版,不仅可以实现#pragma
所有的功能,还能和宏搭配使用.
c++_Pragma("once")
/*****
*头文件
*****/
动态编译使用的是动态库文件进行编译gcc hello.c -o hello
默认使用的是动态编译方法
静态编译使用的静态库文件进行编译gcc -static hello.c -o hello
注意:
优缺点:
以Visual Studio 2022 为例
默认筛选器栏:
修改筛选器栏:
**修改筛选器的作用:**便于针对项目需求分类管理文件.
以Visual Studio 2022为例,一个解决方案可以创建多个项目,
卸载项目:
加载项目:
本文作者:peepdd864
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!