1 / 27

C 语言编程培训

C 语言编程培训. 软件部平台产品. 2003 年 7 月 7 日. 前 言. 疑问: C 语言还要培训吗? 回答: C 语言易学难精,功能强大,而且非常灵活,使用不慎,易造成灾难性后果。尤其在嵌入式系统,尤其强调软件的稳定性。. 提 纲. 1 、字符串的使用 2 、指针的使用 3 、数组和指针 4 、 switch case 的使用 5 、断言的使用 6 、 sizeof 的使用 7 、各种数值类型的边界值 8 、运算符优先级

murray
Télécharger la présentation

C 语言编程培训

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. C语言编程培训 软件部平台产品 2003年7月7日

  2. 前 言 疑问:C语言还要培训吗? 回答:C语言易学难精,功能强大,而且非常灵活,使用不慎,易造成灾难性后果。尤其在嵌入式系统,尤其强调软件的稳定性。

  3. 提 纲 1、字符串的使用 2、指针的使用 3、数组和指针 4、 switch case的使用 5、断言的使用 6、 sizeof 的使用 7、各种数值类型的边界值 8、运算符优先级 9、宏的使用 10、{ }的使用 11、资源的互斥 12、调用时是否回阻塞 13、动态内存的使用

  4. (1)字符串的使用 关键点:字符串必须以‘\0’结尾。 案例1: sprintf(pDstStr, “%s”, pSrcStr); 或strcpy(pDstStr,pSrcStr) /* 当pSrcStr没有以‘\0’结尾时,结果…… */ 问题: (1)、strlen的返回值是多少?考虑下面的数组char szStr[] = {‘1’, ‘0’,’0’,’\0’,’a’,’\0’,’0’}。如果szStr没有初始化时呢? (2)、’\0’等于多少?‘0’==‘\0’ ???

  5. (2)指针的使用 关键点:指针是一种数据类型,其值是内存地址。使用时指针,时刻注意内存地址位置 案例1: void change(char *p) { p = “xyz”;} char *pcStr = “abc”; change(pcStr); printf(“%s”, pcStr); /* 结果等于_______ */ 问题: (1)、指针占几个字节?char ***的意义?struct st1 **的意义? (2)、(*pstr).age == pstr->age ???

  6. (3)数组和指针的使用 关键点:指针和数组是等价的。 案例1: int my_array[] = {1,23,17,4,-5,100}; int *ptr = my_array; int *ptr = &my_array[0]; 问题: (1)、char *p[ ] = {“BOOL”, “OPK”}的等价数组定义是什么?

  7. (4)switch case的使用 关键点:一定有default分支,并在其中增加断言。 问题: (1)、为什么?

  8. (5)断言的使用 关键点:正常情况下不可能出现的情况使用断言。 案例1: int gArray[4] = {1, 2}; int funA(int i) { assert(i < 0); return gArray[i]; } /* 错了,错在哪里了? */ 问题: (1)、什么是正常情况下不可能出现的情况? (2)、如何把断言和容错性结合起来?

  9. (6)sizeof的使用 关键点:sizeof的值是在编译时决定的 问题: int gArray[4] = {1, 2}; int *ptr = (int*)malloc(30); void *pv = malloc(10); (1)、sizeof(gArray) = ?, sizeof(ptr) = ? (2)、sizeof(*ptr) = ?, sizeof(*pv) = ?

  10. (7)各种数值类型的边界值 关键点:注意各种数据类型的最大和最小值 案例: unsigned short i = 0; …… if(i < 16 * 100* 10) {…} 问题: (1)、char和unsigned char的边界值?其他类型? (2)、函数参数尤其注意,为什么?

  11. (8)运算符优先级 关键点:不同类型运算符混合使用,就用括号把它们隔离开来 案例: unsigned short i = 0; …… if(10 < 1 + i >> 3) {…} /* 是等于(1+i) >> 3 还是等于1 + (i >> 3) ?????*/

  12. (9)宏的使用 关键点:宏的参数加();整个表达式加( );定义体中多条语句使用{ }。 案例: #define sum(a, b) a + b …… a = sum(1, 1 + 2); b = sum(1, 2) * 3; …. a = ???? b = ???? 问题: (1)、为什么宏的定义体中有多条语句时要用{ }。

  13. (10){ }的使用 关键点:{ }表示语句块。if…else…分支使用{ } 案例: …… if ( CHECK_FLAG ( old->flags, XXX_WAIT_DELETE ) ) { if ( new == old ) assert( 0 ); xxx_xxx_delete( rn, old, safi ); } UNSET_FLAG ( old->flags, XXX_OLD_SEND ); …… /* 结果….. */ 问题: (1)、什么是语句块?

  14. (11)考虑资源的互斥 关键点:多个任务访问同一数据,一定有互斥保护 提示: (1)、给其他模块提供函数接口时,尤其注意。

  15. (12)调用函数时是否阻塞 关键点:提供和调用函数时,注意是否会阻塞 提示: (1)、调用其他模块提供的函数时,注意是否会阻塞。 (2)、提供函数接口给其他模块时,说明是否会阻塞。 (3)、是否会产生死锁。

  16. (13)动态内存的使用 关键点:时刻提醒自己,动态内存是谁申请的,是多大,该谁释放,何时释放。 提示: (1)、释放一块内存时,确定没有其他分支和任务再使用该内存。 (2)、操作内存块(无论是否是动态的),时刻提醒自己,是否超过内存块 大小。

  17. 总 诀 关键点:编码时怀疑一切,出错也不能死机。 提示: (1)、完全不信任所有的外界输入,包括用户命令和报文。 (2)、对来自其他模块的输入保持怀疑。 (3)、每个环节都可能出现最坏情况。 (4)、任何一个环节出了问题时,可以放弃操作并报错,但决不能死机。

  18. 例 子 要求:实现利用单向链表实现一个队列的操作 struct node struct queue_head struct queue_head *head = NULL; { { int data; int count; struct node *next; struct node *first, *last; }; }; 假设: head已经分配内存,而且初始化了。

  19. no good void queue_add( int data) { struct node *node; node = (struct node*)malloc(sizeof(struct node*)); node->data = data; node->next = NULL; head->last->next = node; head->last = node; head->count++; return 0; } good int queue_in( int data) { struct node *node = NULL; if( NULL == head) { assert(0); return –1; } if( (head->last) || (head->last->next)) { assert(0); return –1; } node = (struct node*)malloc(sizeof(struct node*)); if(NULL == node) { assert(0); return –1; } node->data = data; node->next = NULL; head->last->next = node; head->last = node; head->count++; return 0; } 改进之处 (1)、函数名 (2)、缺少空行 (3)、缺少代码保护,没有考虑异常处理。 (4)、缺少函数头部的说明,缺少注释

  20. good int queue_count( ) { if(( NULL == head) || (0 > head->count)) { assert(0); return –1; } return head->count; } no good int queue_count( ) { return head->count; }

  21. good int queue_out(int *data) { if(NULL == data) { assert(0); return –1; } if((NULL == head) || (0 > head->count)) { assert(0); return –1; } if(0 == head->count) { return –1; } if(NULL == head->first) { assert(0); return -1 } *data = head->first->data; free(head->first) ; head->first = head->first->next; head->count--; return 0; } no good int queue_delete( ) { return head->first->data; } no good void queue_delete(int *data) { if(head->count == 0) { return; } *data = head->first->data; head->first = head->first->next; head->count--; return; }

More Related