标签存档: 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);

继续阅读 »

续行符后不能添加双斜杠注释

今天才发现,原来C语言中续行符 \ 后面不能使用双斜杠 // 进行行注释

C语言测试:想成为嵌入式程序员应知道的0x10个基本问题

本来是想搜索怎样测试C语言编写的嵌入式程序,碰巧找到了这篇文章,觉得不错,转载下,回头仔细看看。
查看原文

C语言测试是招聘嵌入式系统程序员过程中必须而且有效的方法。这些年,我既参加也组织了许多这种测试,在这过程中我意识到这些测试能为带面试者和被面试者提供许多有用信息,此外,撇开面试的压力不谈,这种测试也是相当有趣的。
从被面试者的角度来讲,你能了解许多关于出题者或监考者的情况。这个测试只是出题者为显示其对ANSI标准细节的知识而不是技术技巧而设计吗?这个愚蠢的问题吗?如要你答出某个字符的ASCII值。这些问题着重考察你的系统调用和内存分配策略方面的能力吗?这标志着出题者也许花时间在微机上而不上在嵌入式系统上。如果上述任何问题的答案是“是”的话,那么我知道我得认真考虑我是否应该去做这份工作。
从面试者的角度来讲,一个测试也许能从多方面揭示应试者的素质:最基本的,你能了解应试者C语言的水平。不管怎么样,看一下这人如何回答他不会的问题也是满有趣。应试者是以好的直觉做出明智的选择,还是只是瞎蒙呢?当应试者在某个问题上卡住时是找借口呢,还是表现出对问题的真正的好奇心,把这看成学习的机会呢?我发现这些信息与他们的测试成绩一样有用。
有了这些想法,我决定出一些真正针对嵌入式系统的考题,希望这些令人头痛的考题能给正在找工作的人一点帮住。这些问题都是我这些年实际碰到的。其中有些题很难,但它们应该都能给你一点启迪。
这个测试适于不同水平的应试者,大多数初级水平的应试者的成绩会很差,经验丰富的程序员应该有很好的成绩。为了让你能自己决定某些问题的偏好,每个问题没有分配分数,如果选择这些考题为你所用,请自行按你的意思分配分数。 继续阅读 »

ASCII字符5×7点阵

分享一份不错的ASCII字符5*7点阵。今天使用时遇到了一个非常郁闷的问题,显示小写字母时总是往后挪了一个字,花了好长时间,才找到原来是字符点阵中有一个注释 //\ ,因为 \ 在C语言中是续行符,所以导致把下一行点阵数据给注释掉了,哎,很是郁闷啊。

1
2
3
4
5
6
7
8
9
10
 // _ _ _ _ _
// 0|_|_|_|_|_|
// 1|_|_|_|_|_|
// 2|_|_|_|_|_|
// 3|_|_|_|_|_|
// 4|_|_|_|_|_|
// 5|_|_|_|_|_|
// 6|_|_|_|_|_|
// 7|_|_|_|_|_| BLANK
// 0 1 2 3 4

0x00,0x00,0x00,0x00,0x00, // SP
0x00,0x00,0x4F,0x00,0x00, // !
0x00,0x07,0x00,0x07,0x00, // ”
0x14,0x7F,0x14,0x7F,0x14, // #
0x24,0x2A,0x7F,0x2A,0x12, // $
0x23,0x13,0x08,0x64,0x62, // %
0x36,0x49,0x55,0x22,0x50, // &
0x00,0x05,0x03,0x00,0x00, // ‘
0x00,0x1C,0x22,0x41,0x00, // (
0x00,0x41,0x22,0x1C,0x00, // )
0x14,0x08,0x3E,0x08,0x14, // *
0x08,0x08,0x3E,0x08,0x08, // +
0x00,0x50,0x30,0x00,0x00, // ,
0x08,0x08,0x08,0x08,0x08, // –
0x00,0x60,0x60,0x00,0x00, // .
0x20,0x10,0x08,0x04,0x02, // /

0x3E,0x51,0x49,0x45,0x3E, // 0
0x00,0x42,0x7F,0x40,0x00, // 1
0x42,0x61,0x51,0x49,0x46, // 2
0x21,0x41,0x45,0x4B,0x31, // 3
0x18,0x14,0x12,0x7F,0x10, // 4
0x27,0x45,0x45,0x45,0x39, // 5
0x3C,0x4A,0x49,0x49,0x30, // 6
0x01,0x71,0x09,0x05,0x03, // 7
0x36,0x49,0x49,0x49,0x36, // 8
0x06,0x49,0x49,0x29,0x1E, // 9

0x00,0x36,0x36,0x00,0x00, // :
0x00,0x56,0x36,0x00,0x00, // ;
0x08,0x14,0x22,0x41,0x00, // < 0x14,0x14,0x14,0x14,0x14, // = 0x41,0x22,0x14,0x08,0x00, // >
0x02,0x01,0x51,0x09,0x06, // ?

0x32,0x49,0x79,0x41,0x3E, //@
0x7E,0x11,0x11,0x11,0x7E, //A
0x7F,0x49,0x49,0x49,0x36, //B
0x3E,0x41,0x41,0x41,0x22, //C
0x7F,0x41,0x41,0x22,0x1C, //D
0x7F,0x49,0x49,0x49,0x41, //E
0x7F,0x09,0x09,0x09,0x01, //F
0x3E,0x41,0x49,0x49,0x7A, //G
0x7F,0x08,0x08,0x08,0x7F, //H
0x00,0x41,0x7F,0x41,0x00, //I
0x20,0x40,0x41,0x3F,0x01, //J
0x7F,0x08,0x14,0x22,0x41, //K
0x7F,0x40,0x40,0x40,0x40, //L
0x7F,0x02,0x0C,0x02,0x7F, //M
0x7F,0x04,0x08,0x10,0x7F, //N
0x3E,0x41,0x41,0x41,0x3E, //O

0x7F,0x09,0x09,0x09,0x06, //P
0x3E,0x41,0x51,0x21,0x5E, //Q
0x7F,0x09,0x19,0x29,0x46, //R
0x46,0x49,0x49,0x49,0x31, //S
0x01,0x01,0x7F,0x01,0x01, //T
0x3F,0x40,0x40,0x40,0x3F, //U
0x1F,0x20,0x40,0x20,0x1F, //V
0x3F,0x40,0x38,0x40,0x3F, //W
0x63,0x14,0x08,0x14,0x63, //X
0x03,0x04,0x78,0x04,0x03, //Y
0x61,0x51,0x49,0x45,0x43, //Z

0x00,0x7F,0x41,0x41,0x00, //[
0x02,0x04,0x08,0x10,0x20, /*\*/
0x00,0x41,0x41,0x7F,0x00, //]
0x04,0x02,0x01,0x02,0x04, //^
0x40,0x40,0x40,0x40,0x40, //_

0x00,0x01,0x02,0x04,0x00, //`
0x20,0x54,0x54,0x54,0x78, //a
0x7F,0x48,0x44,0x44,0x38, //b
0x38,0x44,0x44,0x44,0x20, //c
0x38,0x44,0x44,0x48,0x7F, //d
0x38,0x54,0x54,0x54,0x18, //e
0x08,0x7E,0x09,0x01,0x02, //f
0x08,0x54,0x54,0x54,0x3C, //g
0x7F,0x08,0x04,0x04,0x78, //h
0x00,0x48,0x7D,0x40,0x00, //i
0x20,0x40,0x44,0x3D,0x00, //j
0x7F,0x10,0x28,0x44,0x00, //k
0x00,0x41,0x7F,0x40,0x00, //l
0x7C,0x04,0x78,0x04,0x78, //m
0x7C,0x08,0x04,0x04,0x78, //n
0x38,0x44,0x44,0x44,0x38, //o

0x7C,0x14,0x14,0x14,0x08, //p
0x08,0x14,0x14,0x18,0x7C, //q
0x7C,0x08,0x04,0x04,0x08, //r
0x48,0x54,0x54,0x54,0x20, //s
0x04,0x3F,0x44,0x40,0x20, //t
0x3C,0x40,0x40,0x20,0x7C, //u
0x1C,0x20,0x40,0x20,0x1C, //v
0x3C,0x40,0x30,0x40,0x3C, //w
0x44,0x28,0x10,0x28,0x44, //x
0x0C,0x50,0x50,0x50,0x3C, //y
0x44,0x64,0x54,0x4C,0x44, //z

0x00,0x08,0x36,0x41,0x00, //{
0x00,0x00,0x7F,0x00,0x00, //|
0x00,0x41,0x36,0x08,0x00, //}
0x10,0x08,0x08,0x10,0x08 //~

数据处理时边界超出范围引起的问题

实际的问题很简单,要计算n个数据的前后两个数据的波动情况,因为n个数据的前后波动实际只有n-1个,所以在给函数传入参数时没有注意到这一点,因此函数计算时使用一个无效数据,计算了n次差值,但是第n+1个数据是无效的,是的结果偏离真实结果。但是这一错误非常隐蔽,在传感器检测的两次事件是明显分离的时候,计算结果并没有错误(因为此时无效数据和真实数据很接近),但是当两次事件相隔非常近时,就会导致检测结果错误。

看看代码: 继续阅读 »

第 1 页,共 2 页12