GCC

GCC是一个编译器,可以将C语言代码编写为机器码。

支持C/C++,Go,Fortran等语言。

支持MacOS,Windows,Linux等平台。

1
gcc main.c -o main

上述代码:将main编译成一个名字叫main的可执行程序。

%d代表数值,%p代表地址。

指针

*一级指针

指针,比如定义一个指针变量,那个这个指针变量代表的就是另一个变量的地址。

比如:

1
2
3
4
5
6
7
8
int main(){
int a=10;
int *b=&a;
printf("a=%d"\n,a);
printf("b=%p"\n,b);
printf("*b=%d"\n,*b);
return 0;
}

打印出的效果:

a=10,代表数值。

b=ox16db88b58,代表地址。

*b=10,这里因为b本身就是指针变量, *b是解引用指针,他可以获取b指针指向的那块内存地址里存储的值。

**二级指针

1
2
int **c=&b;
printf("a=%d"\n,**c);

打印出的效果:

a=10,这是两次解引用。

数组

一维数组

1
2
3
4
5
6
7
8
int main(){
int a[5]={1,2,3,4,5}
for(int i=0;i<5;i++)
{
printf("a[%d]=%d"\n,i,a[i]);
}
return 0;
}

打印出的效果:

a[0]=1;

a[1]=2;

a[2]=3;

a[3]=4;

a[4]=5;

二维数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int a[3][4]={
{1,2,3,4}
{5,6,7,8}
{9,10,11,12}
}
int main()
{
for(i=0;i<3;i++)
{
printf("\n");
for(j=0;j<4;j++)
{
printf("a[%d][%d]=%d\t",i,j,a[i][j]);
}
}
return 0;
}

打印出的效果:

其中,\t代表智能制表符,能让数据排列更好看。

指针和数组

首先,指针可以直接赋到一个数组上,天然的指向这个数组的第一个元素的地址。同时解引用该指针,就会得到数组的第一个元素的值。

1
2
3
4
5
6
7
8
9
10
int main(){
int a[5]={1,2,3,4,5};
int *p=a;
printf("a的第一个元素的地址是%p\n",p);
printf("a的第一个元素的值是%d\n",*p);
p=p+1;
printf("a的第二个元素的地址是%p\n",p);
printf("a的第二个元素的值是%d\n",*p);
return 0;
}

输出的结果如下:

其中int类型占四个字节,所以a数组中前后两个元素的地址差是4。

static

函数内部的局部变量前面加上static,就会使这个变量在函数结束后,变量的值保留修改,直到整个程序结束,这个局部变量才回归到原本的初始值。

1
2
3
4
5
6
7
8
9
10
void test(){
int a=1;
a=a+1;
printf("a=%d\n",a);
}
int main(){
test();
test();
return 0;
}

输出的结果是:

a=2;

a=2;

若在int前面**加上 静态变量static**

1
2
3
4
5
6
7
8
9
10
void test(){
static int a=1;
a=a+1;
printf("a=%d\n",a);
}
int main(){
test();
test();
return 0;
}

输出的结果:

a=2;

a=3;

typedef

给现有的数据类型起一个“别名”(绰号)

在STM32库函数stm32f10x_gpio.h中,有一段:

1
2
3
4
5
6
typedef struct
{
uint16_t GPIO_Pin;
GPIOSpeed_TypeDef GPIO_Speed;
GPIOMode_TypeDef GPIO_Mode;
}GPIO_InitTypeDef;

用typedef 定义这个结构体叫:GPIO_InitTypeDef,同时这个结构体里有三个变量,GPIO_Pin,GPIO_Speed,GPIO_Mode。用来初始化单片机的GPIO的三个参数,引脚,模式,速度。

然后再主函数中,调用这个typedef的结构体GPIO_InitTypeDef去创造一个特定的结构体,如下:

1
2
3
4
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;

也可通过定义一个指针,指针指向结构体的地址,然后就可以通过这个指针去定义结构体内部的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
typedef struct{
int a;
char b;
}GPIO_InitStruct;
int main(){
GPIO_InitStruct InitStruct;
GPIO_InitStruct *pInitStruct=&InitStruct;
pInitStruct->a=10;
pInitStruct->b='a';
printf("InitStruct.a=%d\n",InitStruct.a);
printf("InitStruct.b=%c\n",InitStruct.b);
return 0;
}

枚举

枚举其实就是用来给一堆整数常量起名字的。

1
2
3
4
5
6
7
8
enum weekday {
SUN,MON,TUE,WED,THU
};
int main(){
day=MON;
printf("%d\n",day);
return 0;
}

输出的结果是:

1

也可以给枚举类型中的某个元素单独赋值。

*和&在C语言中的作用

*****,当他在定义变量时,他是指指针变量这种变量类型。

而在非定义变量时,他是解指针的意思,就是在一个指针变量前加上*就等于这个指针变量指向地址所存储的真实的值。

**&**,指一个变量的地址,这也包括取指针变量的地址。

取整和取余

取整/

1.强制类型转换

比如,有一个浮点类型的数,2.1。

可以通过把他强制转化为int类型。

1
2
float num=2.1;
int result = (int)num;//结果为2

2.整数除法

1
int a=5/2; //结果为2

取余%

1
int a=7%3; 	//a=1

用法1:取余来判断奇偶性

if(a%2==0){}用a除2的余数来判断a是不是偶数,如果结果为0,则a是偶数,否则a为奇数。

用法2:取一个整数的个位数

a%10可以取出a的个位数,比如123%10=3。

a%100可以取出a的最后两位数,比如2143%100=43。