C语言学习笔记

发布 2021-05-12 01:45:28 阅读 7381

函数变量定义。

数据的传递尽量通过函数的参数来实现,函数前面的函数返回值类型最好是表示函数执行的状态。

比如:我们通过串口接收一个字节数据,我们可以定义函数如下:

boolxsmsportserialgetbyte( char * pucbyte )

*pucbyte = udr;

return true;

还可以定义如下:

char xsmsportserialgetbyte( void)

return udr;

第一种方法,调用函数后需要传递出一个接收到的数据,这个是通过函数的参数来传递的。第二种方法,是通过函数的返回值来传递的。

编译。**编译后不能存在warning。

以后一定注意不能忽略编译器的警告

发表于 2008-7-13 22:54:25

1,为什么容易忽略编译器的警告信息?

1)编程时处理各种error已经很让人恼火的了,error自然被放在次要位置;

2)绝大多数下,程序在存在warnings的情况下,在短期内可以正常运行,我们根本看不到错误,导致warning近一步被轻视;

3)没有养成好的工作习惯,带有warning的**是不能交付的,而我们判断交付的标准中往往没有对**提出更为细致的要求。

2,忽视编译警告往往会给我们造成重大损失。

最近的一个项目中,我的程序在实验室测试了1个星期没有出现问题。当设备部署到现场3天后,坏事情终于发生了:设备依次出现死机问题。

再从头分析**, 百思不得其解,痛不欲生的时候注意到了一个编译警告,说一个表达式一直为真。原来发生了下面的错误:

unsigned char i;

for( i = 0; i < 1000; i

变量类型的定义导致了表达式一直为真。为什么开始的测试中不会出现问题哪?原来,这段**是必须程序运行一段时间后才会执行的一段**,在短时间的测试中根本不会进入。

看来编**不能偷懒,偷懒必遭惩罚,你还要费比当时偷懒省的劲多好多倍的劲来弥补,并且这个弥补的过程中你还要承受巨大的压力。跟平时多流汗战时少流血的道理一样的。

3)解决办法。

给自己的编程增加一个规则,带有编译警告的**不能交付。

using a function without a valid prototype is very dangeours.

在一个函数中调用另外一个文件中定义的函数,但是这个函数没有进行声明,会出什么问题哪?

大多数的情况下可能会出现问题,有些情况下,可能是幸运不会出现问题。

看下面这段**:

unsigned long ulwater_max_value=0xabcdeful;

puthexbyte(ulwater_max_value>>24);

puthexbyte(ulwater_max_value>>16);

puthexbyte(ulwater_max_value>>8);

puthexbyte(ulwater_max_value);

其中puthexbyte函数在另外一个c文件中进行了定义,但是在该文件对应的。**件中,我没有对这个函数进行声明。

这样,当运行上面的**的时候,会导致错误的结果,输出的数据全部为0。

改正的方法是,为每个外部函数在。**件做一个相应的声明。每个需要调用这个函数的文件都要包含这个。h头文件。

仍然是上面的**,如果把变量定义为unsigned int 形式,却可以输出正确结果。这有点奇怪,绝对是侥幸,但是,为什么会对哪?即:

unsignedint ulwater_max_value=0xabcd;

//puthexbyte(ulwater_max_value>>24);

//puthexbyte(ulwater_max_value>>16);

puthexbyte(ulwater_max_value>>8);

puthexbyte(ulwater_max_value);

在不声明puthexbyte函数的情况下,仍然能正确输出,为什么哪?

assert(断言)的使用。

编辑: 程序设计发表日期: 2007-05-13 21:56

原创作者:qdieyou,****注。

程序一般分为debug 版本和release 版本,debug 版本用于内部调试,release 版本发行给用户使用。(这个概念可能不大好理解,想想vc下,调试时有个选项,一个是debug,一个是release)

assert(表达式); 的意思是:当表达式为真时,程序继续运行,如果表达市为假,那程序就会停止运行,并提示错误信息。

注意:assert是一个宏,只在debug版本中起作用,在release版本中,该语句是不起任何作用的。

先简单的看一个例子吧!

以下为一个使用了断言的c源程序:

#include <>

#include <>

void test(int *p)

assert(p !=null);

printf("%d", p);

int main(void)

test(null);

编译及运行结果:

qdieyou@qdieyou /cygdrive/e/gcc

gcc -o assert

qdieyou@qdieyou /cygdrive/e/gcc

./assert

assertion "p !=null" failed: file ""line 6

19331 [sig] assert 3288 e:\gcc\ *fatal error - called with threa

dlist_ix -1

hangup

程序说明:由于我们在main函数中传了null指针值给test函数,在test函数执行到assert(p !=null);发现表达式不为真,就终止了程序的运行,并提示错误的行数信息。

注意:由于assert宏只在debug版本中起作用,所以assert一般只用于内部函数对参数有效性进行检查,如果该函数作为一个外部接口来使用时,一般需要利用if,else语句进行防错设计。——qdieyou

以下摘自《c高效编程》

规则6-5-1】使用断言捕捉不应该发生的非法情况。不要混淆非法情况与错误情况之间的区别,后者是必然存在的并且是一定要作出处理的。

规则6-5-2】在函数的入口处,使用断言检查参数的有效性(合法性)。

建议6-5-1】在编写函数时,要进行反复的考查,并且自问:“我打算做哪些假定?”一旦确定了的假定,就要使用断言对假定进行检查。

建议6-5-2】一般教科书都鼓励程序员们进行防错设计,但要记住这种编程风格可能会隐瞒错误。当进行防错设计时,如果“不可能发生”的事情的确发生了,则要使用断言进行报警。

编程的时候,看到下面的一个函数:

emberrorcode

embasciireceive( uchar * pucrcvaddress, uchar **pucframe, ushort * puslength )

emberrorcode estatus = mb_enoerr;

enter_critical_section( )

assert( usrcvbufferpos < mb_ser_pdu_size_max );

/* length and crc check */

if( (usrcvbufferpos >=mb_ser_pdu_size_min )

&& prvucmblrc( (uchar * ucasciibuf, usrcvbufferpos ) 0 )

elseexit_critical_section( )

return estatus;

当看到uchar **pucframe的时候就优点晕了。不就是传出一个地址吗?干吗还要用指向指针的指针?

于是,顺手修改了程序,将那个形参变成了uchar * pucframe,具体的函数也变成了下面的样子:

emberrorcode

embasciireceive( uchar * pucrcvaddress, uchar * pucframe, ushort * puslength )

emberrorcode estatus = mb_enoerr;

enter_critical_section( )

assert( usrcvbufferpos < mb_ser_pdu_size_max );

/* length and crc check */

if( (usrcvbufferpos >=mb_ser_pdu_size_min )

&& prvucmblrc( (uchar * ucasciibuf, usrcvbufferpos ) 0 )

/* s**e the address field. all frames are passed to the upper layed

* and the decision if a frame is used is done there.

*pucrcvaddress = ucasciibuf[mb_ser_pdu_addr_off];

c语言学习笔记

一元二次方程详解。不管我们写什么样的程序,首先要建起构架。c语言的构架是 include intmain void 我们首先需要把三个系数保存到电脑里面,怎么保存呢?我们会以变量的形式保存到电脑里面。比如说 inta 1 intb 2 intc 3 这个 的意思是赋值的意思,不是相等的意思。什么叫变...

C语言学习笔记

a.1.需要成对敲入的符号。2.文件名不要出现。号,否则无法生成。c或。cpp文件,所以不能编译和运行。3.分号 代表一个语句,只有一个 的语句是空语句,所以下面的 不会报错,但表示若条件成立只执行空语句,并且条件语句结束 if a b 等价于 if a b 空语句。4.格式化输出中,建议用 x输出...

C语言学习笔记

求余 求mod 运算符。变量命名规则 只能以字母数字下划线三种字符组成,且第一个字符必须为字母或下划线。scanf d a prindf d a c语言中,变量名是区分大小写的。int 范围 32768 32768 float的指数部分有8bit 2 8 由于是有符号型,所以得到对应的指数范围 12...