C语言学习经验总结
在使用C开发时,一个类型占多少个字节是个很重要的信息元素,
像C语言本身的类型系统并不能体现出这一点,容易使人混乱。
一种好的方式是定义一套简洁易懂又一致的类型
比如:定义一个stdint.h头文件
#ifndef __STDINT_H
#define __STDINT_H
typedef long long int64_t;
typedef unsigned long long uint64_t;
typedef unsigned int uint32_t;
typedef int int32_t;
typedef unsigned short uint16_t;
typedef short int16_t;
typedef unsigned char uint8_t;
typedef char int8_t;
#endif
可以继续用已定义的类型去定义新的类型
typedef uint32_t gfx_Color_t;
用_t后缀表示是自定义类型。(这是很好的技巧)
结构体示例:
typedef struct _gfx_Rect
{
//! brief X position of upper left corner
int16_t x;
//! brief Y position of upper left corner
int16_t y;
//! brief Width of rectangle
int16_t width;
//! brief Height of rectangle
int16_t height;
} gfx_Rect_t;
2. 命名规范(naming convention)
a) 定义变量时使用前缀。比如:g_i8MyGlobalVariable
b) 函数名称添加模块前缀<system>_<subsytem>,比如:hw_dac_Init()
c) 常量、宏全部大写。
3. 要精通并善于用宏定义。
任何一个比较大的工程里,必然存在相当庞大的宏定义。理解并用好宏是精通C语言的关键。
a) 程序里出现任何确定的数字都应该用宏来代替,以达到以后修改只修改宏即可的目的;当然也更容易代码理解和阅读。
b) 充分理解#define 替换的本质,看下面的例子,巧妙实现了一种继承机制:
#define WIDGET_BASIC_PROPERTIES
struct _Widget *pNext;
struct _Widget *pParent;
struct _Widget *pChild;
const uim_WidgetClass_t *pClass;
gfx_Rect_t Rect;
gfx_DeviceContext_t *pDC;
uint8_t u8AlphaChannel;
gfx_Color_t u32ChromaColor;
struct {
uint16_t u16WidgetID : 16; //这里是位域,不是结构体
uint16_t uHeartBeat : 16; //位域的宽度不能超过它前面类型的大小的宽度,
//并不是通常所说的不能超过一个字节(8位)
//只是往往用到位域的时候都是用unsigned等小类型的,特别是一些布尔类型的位域成员。感觉这里没必要用位域。
};
struct { //注意:这里也是位域
uint8_t MsgGroup :8;
unsigned bTransparent : 1;
unsigned bInvisible : 1
//! brief Macro indicating the end of the base widget properties.
#define WIDGET_END_OF_BITFIELD_PROPERTIES }
typedef struct _Widget {
WIDGET_BASIC_PROPERTIES;
WIDGET_END_OF_BITFIELD_PROPERTIES;
} Widget_t;
typedef struct _myWidget {
WIDGET_BASIC_PROPERTIES;
WIDGET_END_OF_BITFIELD_PROPERTIES;
uint8_t u8MyData;
} MyWidget_t;
在#define中加反斜杠()表示续行。
这是一个非常妙的用法。它将_Widget结构体的成员抽出来,定义成宏,以实现继承机制。
也就是说继承自这个Widget_t的类只要加入上面的宏也就拥有了与之相同的成员。
它这里甚至允许子类继续扩展父类的位域,利用的技术就是把位域定义中的最后一个括号定义成宏,因为宏是纯粹的替换。
4. 善用结构、枚举、位域、联合
要熟练掌握它们,特别是前两个,会有大量的应用,然后是位域,往往嵌套在结构体定义中。
结构体可以看做是一种自定义的数据类型,它还有一个很重要的特性,就是结构体可以相互嵌套使用,但也是有条件的,不能在结构体中包含自身结构体变量,但自身指针是可以的,其他struct变量也是可以的。
struct test
{
char name[10];
float socre;
test *next;
};//这样是正确的!
struct test2
{
char name[10];
float socre;
};
struct test
{
char name[10];
float socre;
test2 ts;
};//这样是正确的!
struct test
{
char name[10];
float socre;
test next;
};//这样是错误的!
4. 熟练应用条件编译
在涉及模块非常多的大工程里,会有许多比如:选择性初始化、选择性处理等。这时就会用到条件编译,这是非常有用的功能。例:#if defined(ENABLE_BATTERY_CHARGE)
a) 基本格式:
#ifdef aa 或if defined(aa)
//处理代码
#endif
b) 为了防止头文件重复引入,也用到了此技术
c) 为了使C/C++都可使用某头文件中声明的函数原型,也用到了此技术。
例:#ifdef __cplusplus
extern "C" {
#endif
RtStatus_t km_OpenTaskManager(Widget_t *pWidget);
#ifdef __cplusplus
}
#endif
5. 精通位操作
6. 源文件的一般结构
////////////////////////////////////////////////////////////////////////////////
//! 说明
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Includes and external references
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Externs
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Definitions
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Prototypes
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Variables
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Code
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// End of file
///////////////////////////////////////////////////////////////////////////////
更多阅读
2014年科目二直角转弯考试技巧经验总结 科目2直角转弯技巧
2014年科目二直角转弯考试技巧经验总结——简介我是今年3月份报的驾校,8月底刚刚考完科目2,其中科目二考五项,倒库、侧方停车、坡起坡停、直角转弯、曲线行驶。遗憾的是我是补考通过的科目二,直角转弯虽然大家都认为是很简单,但是也是经
高中生物学习方法与经验总结
高中生物,是高中阶段的一门重要课程。对于理科生来说,尤其如此。要学好高中生物课,不仅要有明确的学习目的,还要有勤奋的学习态度和科学的学习方法。针对生物学科的特点,要学好高中生物,建议做到以下几个方面。高中生物学习方法与经验总结
个人对淘宝网店经营技巧经验总结 淘宝网店经营
个人对淘宝网店经营技巧经验总结——简介很多人都知道的目前淘宝作为国内最大的C2C网站,汇聚了全国各地的商界精英。在高手如云的网上卖场,为了争取有限的客户,必然注意一些网店的经营方法策略,才能获得属于自己的市场份额。那么在淘宝
转载 C语言:随机函数rand()、srand()、random()和rando
原文地址:C语言:随机函数rand()、srand()、random()和randomized()的区别和用法作者:猎空声明一点:在VC++中,没有random()和randomize()函数,只有rand()和srand()函数。其中,random()和randomize()函数的使用的方法分别与rand()和srand()
使用Visual C++6.0编写简单C语言程序入门教程 visual c 编写c语言
使用Visual C++6.0编写简单C语言程序入门教程——简介本教程适用于C语言初学者,使用VC++6.0编写简单的程序。Visual C++6.0作为学习C语言的编程工具在合适不过了,工具比较简洁,容易上手。下面我将一步步带领大家一步步操作,教会大家如何