分类存档: C语言

Look at this long expression of function declaration

Look at this long expression of function declaration

extern FUNC( Std_ReturnType, FEE_CODE ) Fee_Write(
VAR( uint16, AUTOMATIC ) BlockNumber,
P2VAR( uint8, AUTOMATIC, FEE_APPL_DATA ) DataBufferPtr);

There are four macro in this expression: FUNC, VAR, P2VAR, Std_ReturnType, these definition

/*
* @violates @ref Compiler_h_REF_4 In the definition of a function-like macro each instance of a
* parameter shall be enclosed in parentheses
*/
#define FUNC(rettype, memclass) rettype

/*
* @violates @ref Compiler_h_REF_4 In the definition of a function-like macro each instance of a
* parameter shall be enclosed in parentheses
*/
#define VAR(vartype, memclass) vartype

/*
* @violates @ref Compiler_h_REF_4 In the definition of a function-like macro each instance of a
* parameter shall be enclosed in parentheses
*/
#define P2VAR(ptrtype, memclass, ptrclass) ptrtype *

/**
* @brief This type can be used as standard API return type which is shared between the RTE and the
* BSW modules.
* @implements DBASE12002
*/
typedef uint8 Std_ReturnType;

So the long declaration expression should look like this after precompile :

extern uint8 Fee_Write(uint16 BlockNumber, uint8* DataBufferPtr);

It’s simple, So don’t be scared by the long expression.

PS: AUTOSAR <Specification of Compiler Abstraction> defined how to implement the Complier.h file.

 

C标准预定义宏__FILE__和f__LINE__等

C/C++标准定义了标准预定义宏,这些宏对所有遵循该标准编译器有效,这些宏在程序调试时是比较有用的。但我偶尔会忘了怎么写,在程序里到处找,所以把他记录到这里。这些预定义宏以双下划线开始、结束。

#include <stdio.h>
int main(int argc, char *argv[])
{
printf(“%s\n”, __FILE__);
printf(“%s\n”, __FUNCTION__);
printf(“%d\n”, __LINE__);
printf(“%s\n”, __DATE__);
printf(“%d\n”, __STDC__);
printf(“%s\n”, __TIME__);
}

 

for循环第二个表达式使用多重条件的写法

for循环有三个表达式,第一个表达式进行测试,只在循环开始的是自学一次;第二个表达式是判断条件,每次执行循环之前进行求值,如果为假则循环结束;第三个表达式在每次循环结束时进行计算。这里三个都是表达式,那么就意味着可以进行运算。

有时候我们希望for循环判断两个条件来结束循环,有时候希望每次循环结束后改变两个变量的值,这样的表达式该怎样写呢?

这里就要说说逗号运算符。在C语言中,多个表达式可以用逗号分开,其中用逗号分开的表达式的值分别计算,但整个表达式的值是最后一个表达式的值。

因此for循环的第二个表达式条件判断时应该使用 && 和 || 等关系运算符,而第三个表达式可以使用逗号运算法。例如:

for (i=0,j=0; (i<10)&&(j<5); i+=2,j+=1)
{
……..
}

该for语句的作用是,每次循环开始前判断i<10和j<5是否同时成立,循环结束后修改i和j的值。

局部变量使用指针方式赋值可能会导致异常

从协议解析数据是为了提高效率,我常常使用指针直接操作内存地址来替代移位操作,如下 :

    *((u8*)&a+1) = *(pbuf + 0);
    *((u8*)&a+0) = *(pbuf + 1);

继续阅读 »

自增自减运算符++/–与函数调用

同事在从Keil向IAR移植时遇到一个函数调用产生的问题,细究原因,应该是 ++ 运算符和函数赋值顺序引起的。先看如下代码:

#include   \<stdio.h\>
void test_func(char a, char b)
{
  printf("\r\na=%d b=%d",a,b);
}

void main(void)
{
  char buf[3] = {1,2,3};
  char i = 0;
  char c = 0,d = 0;
  c = i++ + i++;
  printf("\r\nc=%d i=%d",c,i);
  i=0;
  printf("\r\npara1=%d para2=%d",i++,i++);
  i = 0;
  test_func(buf[i++],buf[i++]);
}

上面代码的输出结果如下: 继续阅读 »

不在同一条语句中多次使用自增运算符

今天遇到一个问题,使用串口打印数组中的连个字节发现输出的都是第一个字节的内容,语句如下:
hal_Printf1(“\r\na=%d b=%d”,*(pRate++),*(pRate++));
通过在网上搜索,得到的结论是不要连续使用自增运算符,我把它总结为:不在一条语句中多次使用自增自减运算符。
具体分析请参考 Malash’s Blog 《为什么不建议在C语言中连续使用自增自减运算符

三目运算符使用时的注意

三目运算符使用起来很方便,但是也容易出错,今天就发现了一处不起眼的错误,通常情况下还不易发现。

看如下表达式:
a = 2 + (c > d)?(c):(d);
本来的意图是将c和d中较大者加2赋值给a,但是语句执行的结果是时钟将c的值赋值给a。

原因是三目运算符的  ? :  的优先级是13,倒数第三,加运算优先级高于它,所以?左边永远为真。

故,三目运算符参与混合运算时一定要在最外层加上括号(通常我们只记得给三个参与运算的数据加括号)。

 

使用fgetc读取文件合理判断文件结束

char c;
while ((c = fgetc (rfp))!= EOF);
当文件结束时fgetc函数返回的是EOF,即-1,也就是0xff。而如果数据文件中恰好有数据0xff,则返回的也是0xff,那么上面的代码会误判为文件结束。
问题在哪里?
请看fgetc函数的原型:int fgetc ( FILE * stream );
实际上,getc 以 unsigned char 的方式读取文件流, 扩张为一个整数,并返回. 换言之, getc 从文件流中取一个字节, 并加上24个零,成为一个小于256的整数, 然后返回。
如果用下面的代码就不会出现误判文件结束的问题
int c;
while ((c = fgetc (rfp))!= EOF);

第 1 页,共 7 页12345...最旧 »