ZYNQ的SDK是用C语言进行开发的,C语言可以说是当今理工类大学生的必备技能。我本科学C语言时就是对付考试而已,导致现在学ZYNQ是一脸懵逼。现在特开一帖,整理一下C语言的基础知识。

一、定义

1.关键字

char      :定义一个8位的变量,就是一个字节。
short int :定义一个16位的变量,就是两个直接
int      :定义一个32位(一般情况下)的变量,就是四个字节。
float     :定义一个精度为6位小数点的浮点型小数,超过精度的数据会有偏差,本身即有符号型。
double    :定义一个精度为15位的小数点的浮点型小数,超过精度的数据会有偏差,本身即有符号型。
unsigned   :加在前面四个关键字前面,表示无符号的数据,就是“只有正数”的意思。
signed   :加在前面四个关键词前面,表示有符号的数据,就是“有正负数”的意思。
signed char :等效于char ,因为signed 可以省略。也就是,如果不定义unsigend,那肯定是有符号的。 #define    :宏定义

2.技巧:typedef类型说明符

unsigned char a; //定义一个无符号8位整型变量a
//-----------------------------------------------------
typedef unsigned char uint8_t; //typedef用法
uint8_t a; //更加明了

实际上很多头文件已经帮我们这样定义好了

typedef signed         char int8_t;
typedef signed short char int16_t;
typedef signed int int32_t;
typedef signed _INT64 int64_t; typedef unsigned char uint8_t;
typedef unsigned short char uint16_t;
typedef unsigned int uint32_t;
typedef unsigned _INT64 uint64_t;
.
.
.

3.强制转换

  如果结果是浮点型的数据,要保证在计算过程中的变量也是浮点型,如果不是浮点型,可以采用强制类型转换转换成浮点数。

c = (float)a + (float)b; //将a、b强制转换成float型

二、位操作

1.定义

2.技巧

不改变其他位的状况下,对某几位赋值,分两步实现

//①用 & 进行清0操作:
//-------------------------------------------------------
a &= 0x0F; //对第4-7位清0,第0-3位的值不变 //②用 | 进行赋值操作:
//-------------------------------------------------------
a |= 0x20; //对第4-7位赋值为2,第0-3位的值不变

三、函数

1.无参数,无返回值

void send123(void)  //void不写也行
{
printf("%d",);
printf("%d",);
printf("%d",);
} int main(void)
{
USART1_Init();
send123;    //函数调用
while()
{
}
} //等价于 ---------------------------------------- int main(void)
{
USART1_Init();
printf("%d",);
printf("%d",);
printf("%d",);
while()
{
}
}

2.有参数,无返回值

void sendx23(uinit8_t x,uinit8_t y) //括号里是形参
{
printf("%d",x);
printf("%d",y);
printf("%d",);
} int main(void)
{
USART1_Init(); sendx23(1,2); //函数调用,括号里的是实参 while()
{
}
} //等价于 ---------------------------------------- int main(void)
{
USART1_Init(); printf("%d",);
printf("%d",);
printf("%d",); while()
{
}
}

3.有参数,有返回值

uinit8_t sendxyz(uinit8_t x,uinit8_t y,uinit8_t z)
{
z = x + y;
return z;
} int main(void)
{
uint8_t a;
USART1_Init(); a = sendxyz(,,); //a = z = 1 + 2;
printf('%d',a); while()
{
}
}

四、数组

  注意,数组名a和&a[0]等价,C语言规定只能逐个引用数组元素,不能一次引用整个数组。

1.一维数组

uint8_t x[]={,,}; //也可写作 x[]
//内部展开可得:
//x[0]=0;
//x[1]=1;
//x[2]=2;

2.二维数组

uint8_t x[][] = {{,},{,},{,}};   //5行2列
uint8_t x[][] = {,,,,,}      //等价写法

3.数组和指针

  数组的名字就代表数组的首地址,可将数组的名字赋给和其相同内容的指针,即该指针指向了数组。

int *a,*b,c[];
a = c; //将数组c的首地址赋值给指针a
b = &c[]; //将数组c的首元素c[0]的地址赋值给指针b //指针a、b都指向数组c //a = &c; //错误写法!

五、变量,先定义再使用

1.局部变量(优先级最高)

  函数内定义的变量,只能作用于本函数内。

void main()
{
uint_8 x;
}

2.全局变量

  函数外定义的变量,可以作用于各个函数中。

uint_8 x;  

void main()
{
}

3.extern

  extern 可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。这里面要注意,对于 extern 申明变量可以多次,但定义只有一次,且不能重复赋值。

①文件内

//只有b函数才能使用变量x
//--------------------------------------
void a()
{
} uint32_t x; void b()
{
} //使用extern
//--------------------------------------
void a()
{
extern uint32_t x; //表示在某处已经定义过
} //放到最前面也可以
uint32_t x; 
void b()
{
}

②跨文件

// file1.c
//-------------------------------
int a; int main
{
} // file2.c
//-------------------------------
extern a; int main
{
}

4.static

  static定义的值称为静态,生命周期为整个程序周期。

①局部static,作用域为局部作用域,调用时只会在初次使用时执行初值,后面继续调用的值等于上次结果的值。

//调用多次 int getValue(),flag = 1,1,1,1,1,1,1,1,1......
//-----------------------------------------------------------------
int getValue()
{
int flag=0;       //每次都会执行
flag++;
return flag;
} //调用多次 int getValue(),flag = 1,2,3,4,5,6,7,8,9......
//------------------------------------------------------------------
int getValue()
{
static int flag=0; //只会执行一次
flag++;
return flag;
}

②全局static,其作用域为本文件内,其他文件用extern调用是错误的。

// file1.c
//-------------------------------
int a;
static int b; int main
{
} // file2.c
//-------------------------------
extern a;   //这是对的
extern b; //这是错的!!!
int main
{
}

六、指针

1.指针概念

指针变量a 地址,即0089
指针变量a 值,即0090 指针变量a的值为指针的地址,该地址为另一个变量b的地址
变量b的地址存放着b的内容,即100

 2.指针的基本用法

// 1.取地址运算 &,可以得到指针变量本身的地址
// 2.取内容运算 *,可以得到地址数据对应存储单元的内容 int main(void)
{
uint8_t *a; //对象是地址
uint8_t b; //对象是数据 USART1_Init(); a = &b; //赋值b的地址0090
b = ; //赋值数据80 printf("%d",&b); //发送的是b的地址:0090
printf("%d", b); //发送的是b的数据:100
printf("%d",&a); //发送的是a的地址:0090
printf("%d", a); //发送的是a的内容即b的地址:0090
printf("%d",*a); //发送的是b的数据:90 while()
{
}
}
//int *x; 定义一个“指针型的”变量x,*看成是语文层面的对x的修饰词

3.常见混淆式子

*(&a) <=> a    //二者等价
&(*a) <=> a //二者等价 *a++ //先计算 *a ,再计算 a++
*(a++) //先计算 a++ ,再计算 *a
*(++a) //先计算 a++,再计算 *a

七、结构体

  结构体是个好东西,在不改变入口参数的情况下,只需要改变结构体的成员变量就可以达到增加函数的路口参数的目的。
1基本概念
①格式:
struct 结构体名
{
成员列表;
}变量名;
//for example
//-----------------------------------
struct U_TYPE
{
int BaudRate
int WordLength;
};usart1,usart2;

②也可以在结构体申明的时候定义变量,申明之后再定义:

struct 结构体名字 结构体变量列表 ;
//for example
//------------------------------------
struct U_TYPE
{
int BaudRate
int WordLength;
};
struct U_TYPE usart1,usart2;

③结构体成员变量的引用方法是:

结构体变量名字.成员名
//for example
//------------------------------------
usart1.BaudRate = 1; //对其赋值
usart1.WordLength = 2; //对其赋值 //或者这样也行
//------------------------------------
struct U_TYPE
{
int BaudRate
int WordLength;
}usart1={1,2};

2.结构体指针 

//①定义
//-----------------------------------------------------------
struct U_TYPE *usart3;//定义结构体指针变量 usart1; //②引用方法
//-----------------------------------------------------------
usart3->BaudRate; //访问 usart3 结构体指针指向的结构体的成员变量 BaudRate
*usart3.BaudRate; //二者等价

 3.结构体数组

  结构体变量作为元素的数组,该数组的每个元素都是一个结构体。

 4.结构体和typedef

  typedef 用于为现有类型创建一个新的名字,或称为类型别名,用来简化变量的定义。

//①为该结构体定义一个别名GPIO_TypeDef
//---------------------------------------------------
typedef struct //本名都可以不要
{
__IO uint32_t MODER;
__IO uint32_t OTYPER;
} GPIO_TypeDef; //②通过 GPIO_TypeDef 来定义结构体变量:
//---------------------------------------------------
GPIO_TypeDef GPIOA; //常见于函数形参
 

八、其他知识补充

1.ifdef条件编译

不仅是C语言还是Verilog,都会经常使用这个功能。

// 标识符已被#define定义过则编译程序段1,否则编译程序段2
//===========================================================
#ifdef 标识符
程序段1
#else
程序段2
#endif // #else部分也可以没有
//===========================================================
#ifdef
程序段1
#endif

2.i++和++i

int main(void)
{
uint8_t i;
USART1_Init(); i = ;
printf("%d",i++); //等效于 printf("%d",i);即打印结果为5
// i = i+1;
while()
{
}
} //----------------------------------------------------- int main(void)
{
uint8_t i;
USART1_Init(); i = ;
printf("%d",++i); //等效于 printf("%d",i=i+1);即打印结果为6
// i = i;
while()
{
}
}

参考资料:

[1]瑞生.边学边用攻破C语言.视频教程

[2]康莉, 杨国祥, 项延铁. 零点起飞学C语言[M]. 清华大学出版社, 2013.

[3]正点原子STM32教程

ZYNQ笔记(0):C语言基础知识复习的更多相关文章

  1. 复习笔记——1. C语言基础知识回顾

    1. 数据类型 1.1 基本数据类型 整型:int, long,unsigned int,unsigned long,long long-- 字符型:char 浮点型:float, double-- ...

  2. C语言程序设计做题笔记之C语言基础知识(下)

    C 语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行 事.并且C是相当灵活的,用于执行计算机程序能完成的 ...

  3. C语言程序设计做题笔记之C语言基础知识(上)

    C语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序(即一组指令),并让计算机依指令行事.并且C是相当灵活的,用于执行计算机程序能完成的几乎 ...

  4. linux c 笔记-3 c语言基础知识

    关键字 数据类型: 简单(7):int long short float double char enum 复杂(2):struct union 类型修饰符(8):auto unsigned sign ...

  5. ios开发学习笔记001-C语言基础知识

    先来学习一下C语言基础知识,总结如下: 在xcode下编写代码. 1.编写代码 2.编译:cc –c 文件名.c 编译成功会生成一个 .o的目标文件 3.链接:把目标文件.o和系统自带的库合并在一起, ...

  6. OC语言基础知识

    OC语言基础知识 一.面向对象 OC语言是面向对象的,c语言是面向过程的,面向对象和面向过程只是解决问题的两种思考方式,面向过程关注的是解决问题涉及的步骤,面向对象关注的是设计能够实现解决问题所需功能 ...

  7. 李洪强iOS开发之OC语言基础知识

    OC语言基础知识 一.面向对象 OC语言是面向对象的,c语言是面向过程的,面向对象和面向过程只是解决问题的两种思考方式,面向过程关注的是解决问题涉及的步骤,面向对象关注的是设计能够实现解决问题所需功能 ...

  8. Golang 入门系列(三)Go语言基础知识汇总

    前面已经了 Go 环境的配置和初学Go时,容易遇到的坑,大家可以请查看前面的文章 https://www.cnblogs.com/zhangweizhong/category/1275863.html ...

  9. Spring Cloud微服务实战阅读笔记(一) 基础知识

    本文系<Spring Cloud微服务实战>作者:翟永超,一书的阅读笔记. 一:基础知识   1:什么是微服务架构     是一种架构设计风格,主旨是将一个原本独立的系统拆分成多个小型服务 ...

随机推荐

  1. Linux:搭建GitLab

    0.写在前面 GitLab官方明确要求最低配置2核4G,如果配置过低,会出现502错误. 1.安装SSH #安装ssh sudo yum install -y curl policycoreutils ...

  2. tidyr

    tidyr包主要提供了数据整理和清洗的功能,包括 1. 数据框的变形 2. 处理数据框中的空值 3. 根据一个表格衍生出其他表格 4. 实现行或列的分隔和合并 该包将要用的数据处理成标准且统一的数据框 ...

  3. Gradle系列教程之依赖管理

    这一章我将介绍Gradle对依赖管理的强大支持,学习依赖分组和定位不同类型仓库.依赖管理看起来很容易,但是当出现依赖解析冲突时就会很棘手,复杂的依赖关系可能导致构建中依赖一个库的多个版本.Gradle ...

  4. RFC-6455 The WebSocket Protocol 浅读

    什么是WebSokcet? WebSocket是一种协议,并且是各大主流浏览器作为客户端支持的协议.它的目标就是用来替代基于 XMLHTTPRequest和长轮询的解决方案.应用在时时弹幕,消息推送, ...

  5. NioEventLoopGroup源码分析与线程设定

    我的以Netty Socket编程的代码为例, 1.EventLoopGroup 进入EventLoopGroup,这是一个特殊的EventExecutorGroup,在事件循环中,在selectio ...

  6. TOKEN验证防止CSRF攻击的原理

    TOKEN验证防止CSRF攻击的原理.CSRF中文名是跨站请求伪造攻击,黑客可以通过CSRF攻击来伪造我们的身份,从而进行不法的活动.比如说是以我们的身份进行转账,发送邮件等操作. 要想做到预防CSR ...

  7. Error-ASP.NET:无效的 JSON 基元: object。

    ylbtech-Error-ASP.NET:无效的 JSON 基元: object.  1.返回顶部 1. “/”应用程序中的服务器错误. 无效的 JSON 基元: object. 说明: 执行当前 ...

  8. Linux安装fcitx输入法(命令安装)

    Linux安装fcitx输入法(命令安装)   打开终端安装输入法 sudo apt-get install im-switch libapt-pkg-perl fcitx fcitx-table-w ...

  9. Win64 驱动内核编程-33.枚举与删除对象回调

    转载:http://www.voidcn.com/article/p-wulgeluy-bao.html 枚举与删除对象回调 对象回调存储在对应对象结构体里,简单来说,就是存储在 ObjectType ...

  10. 【Layui】 layui表单必填项带*样式

    直接上代码 .layui-form-label.layui-required:after{ content:"*"; color:red; position: absolute; ...