目录
一.主函数
int main()
{
return 0;
}
二.变量
变量名:在C语言中属于标识符,命名有以下严格的规范
- 只能有字母(包括大,小写),数字,下划线(_)组成
- 不能以数字开头
- 长度不能超过63个字符
三.关键字
注:不能做变量名!
auto | break | case | char | const | continue | default | do | double |
enum | extern | float | for | goto | register | inline | int | long |
return | restrict | short | signed | sizeof | static | struct | void | switch |
typeof | union | unsigned | volatile | else | while | if |
static
static用来修饰变量和函数的:
- 修饰局部变量:改变了变量的生命周期,到程序结束,生命周期结束
- 修饰全局变量:使全局变量只能在本文件中使用
- 修饰函数:使函数只能在本源文件中使用
struct
结构体的声明:
struct tag
{
member-list;
}variable-list;
结构体成员的访问:
- 结构体变量.成员变量名
- 结构体指针->成员变量名
四.数据类型
整型数据
基本整形:
类型 | 字节(8bit) | 取值范围 |
int | 4 | -2^31 ~ 2^31-1 |
unsigned int | 4 | 0 ~ 2^31-1 |
总结:(n位)有符号数:-2^n-1 ~ 2^(n-1)-1 无符号数:0 ~ 2^n-1
整形的进制:
八进制:以0为前缀(012 = 十进制的10)
十六进制:以0x为前缀(0x1A2B = 十进制的6699)
在printf()的进制占位符如下:
- %d:十进制整数
- %o:八进制整数
- %x:十六进制整数
- %#0:显示前缀为0的八进制整数
- %#X:显示前缀为0X的十六进制整数
字符型数据
字符‘1’:占一个字节,(ASCII码为49:00110001)
整数1:占4个或者8个字节(00000000 00000000 00000000 00000001)
浮点型数据
m*b^e的形式:m为小数部分,b是基数(通常为2),e是指数部分
布尔类型
#include<stdbool.h>
bool flag=false;
五.操作符
算数操作符
+ - * / %
移位操作符
<< 左移操作符
>>右移操作符
注:移位操作符的操作数只能是整数
左移操作符:
左边抛弃,右边补0
右移操作符:
1.逻辑移位:左边用0填充,右边丢弃
2.算术移位:左边用原该值的符号位填充,右边丢弃
位操作符
& 按位与
| 按位或
^ 按位异或
赋值操作符
+= -= *= /= %= >>= <<= &= |= ^=
单目操作符
! 逻辑反操作
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 前置,后置--
++ 前置,后置++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
关系操作符
> >= < <= != ==
逻辑操作符
&& 逻辑与
|| 逻辑或
条件操作符
exp1?exp2 :exp3
逗号表达式
exp1,exp2,exp3,...expN
逗号表达式,从左往右依次进行,整个表达式的结果是最后一个表达式的结果。
下标引用,函数调用和结构成员
1.[ ] 下标引用操作符
操作数:一个数组名+一个索引值
2.( ) 函数调用操作符
接受一个或多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数
3.访问一个结构的成员
. 结构体.成员名
-> 结构体指针->成员名
六.数组
一维数组的定义
类型符 数组名[常量表达式];
一维数组的初始化
- 在定义数组时对全部数组元素赋予初值。如 int a[3]={1,2,3};
- 可以只给一部分元素赋值。如 int a[10]={1,2,3};
- 如果想使一个数组元素全部为0。如 int a[10]={0};
- 在对全部数组元素赋值的时候,由于数据的个数已经确定,因此可以不指定数组长度。如 int [4]={1,2,3,4};= int a[]={1,2,3,4};
一级数组传参
#include<stdio.h>
void test1() //可以写:int arr[ ] 或 int arr[10] 或 int *arr
{
}
void test2() //可以写:int *arr[20] 或 int **arr
{
}
int main()
{
int arr[10]={0};
int *arr2[10]={0};
test(arr);
test2(arr2);
return 0;
}
二维数组的定义
类型符 数组名[常量表达式][常量表达式];
二维数组的初始化
- 分行给二维数组赋初值。如int a[2][3]={{1,2,3},{4,5,6}};
- 可以将所有数据放到一个花括号内,按数组元素在内存中的排序顺序对各个元素赋初值。如 int a[2][3]={1,2,3,4,5,6};
- 可以对部分元素赋初值。如 int a[2][3]={{1},{5}};
- 如果对全部元素都赋初值,则第一维的长度可以不指定,但第二维的长度不能省。如 int a [2][3]={1,2,3,4,5,6}; = int a [ ][3]={1,2,3,4,5,6}; = int a [][3]={{1,2,3},{}};
注:一个{ }是行,{ }里面是列。
数组名是什么?
数组名是数组首元素的地址
但有两个例外:
①.sizeof (数组名):表示整个数组,计算整个数组的大小
②.&数组名:表示整个数组,取出的是整个数组的地址
二级数组传参
#include<stdio.h>
void test1() //可以写:int arr[3][5] 或 int arr[ ][5] 或 int (*arr) [5]
{
}
int main()
{
int arr[3][5]={0};
test(arr);
return 0;
}
注: int (*arr) [5] 是数组指针,可以指向一个有5个整形元素的数组
七.指针
一个变量的地址称为该变量的“指针”
指针变量就是地址变量,用来存放地址,其值是地址
一级指针
定义指针变量
类型名 *指针变量名;
注:(1)指针变量前的“*”表示该变量类型为指针型变量
(2) 在定义指针变量时必须指定其类型
(3)指针变量中只能存放地址(指针)
引用指针变量
- 给指针变量。如:p=&a;//指针变量p的值就是变量a的地址
- 引用指针变量指向的变量。如:printg("&d",*p);//以整数的形式输出a的值
- 引用指针变量的值。如:printf("%o",p)://以八进制形式输出变量p的值
通过指针引用数组
所谓数组元素的指针就是数组元素的地址
p = &a[0];
//p=a
int *p = &a[0];
//int *p=a
//int *p; p=&a[0];
//int *p; p=a;
引用数组元素时指针的运算
- 如果指针变量p已经指向数组的一个元素,则p+1指向同一数组中的下一个元素,p-1指向同一数组中的上一个元素。
- 如果p的初值为&a[0],则 p+i 和 a+i 就是数组元素 a[i] 的地址。
- *(p+i)=*(a+i)= a[ i ] 。
- 如果指针变量p1和p2都指向同一数组,则p2-p1的值(两个地址之差)/(数组元素长度)=指针之间的元素个数。
总结
- 指针变量:用来存放地址的变量
- 指针是用来存放地址的,地址是唯一标识一块地址空间的
- 指针大小在32位平台上是4个字节,在64位平台上是8个字节
- 指针类型的意义:①指针解引用的权限有多大 ②指针走一步能走多远
野指针
概念
就是指针指向的位置是不可知的
如何规避野指针
- 指针初始化
- 小心指针越界
- 指针指向空间释放及时置NULL
- 避免返回局部变量的地址
- 指针使用前检查有效性
二级指针
int a =10;
int *pa = &a; //一级指针
in* *ppa = &pa; //二级指针
注:*ppa=pa (int* 是指pa的类型)// **ppa=*pa=a
指针数组
int* arr[10]; //整形指针的数组
char* arr[4]; //一级字符指针的数组
数组指针
int(*p) [10];