macro evaluation in compiler

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

macro evaluation in compiler

跳至解决方案
2,874 次查看
rlw
Contributor I

I am currently using "ANSI-C/cC++ Compiler for HC12 V-5.0.40 Build 10020, Jan 21 2010".

 

In my code, I am using this macro:

Mk4Bytes(x) { (((u8)((x) >> 24)) , ((u8)((x) >> 16)) , ((u8)((x) >> 8)) , ((u8)(x))) }

 

which I have used successfully in other compilers. However, when I used it to initialize a field in a structure, I got the error "ERROR C2207: Initializer must be constant"

 

Here is a excerpt of my code:

 

typedef unsigned char u8;

typedef struct {

u8 partnumber[4];

u8 version[2];

}  tIDheader;

 

#pragma CONST_SEG IDHEADER

const tIDheader IDheader = {

Mk4Bytes(12345678),

"A0"

};

 

While I know that I could simply change the field definition to use "unsigned long" instead of an array of bytes, the struct is actually defined in automatically generated code, so I am not allowed to change the definition.

 

Anyway, the value given to the macro is a constant so the resulting expression is a constant expression, so I would expect the compiler to replace the expression with { 0x00, 0xBC, 0x61, 0x4E }, which is a constant initializer.

 

As I said, I have used this macro successfully with other compilers. Is this a bug with this compiler?

标签 (1)
标记 (1)
0 项奖励
回复
1 解答
1,874 次查看
CompilerGuru
NXP Employee
NXP Employee

The provided macro contains one pair of braces too much .

Try:

 

 

#define Mk4Bytes(x) { ((u8)((x) >> 24)) , ((u8)((x) >> 16)) , ((u8)((x) >> 8)) , ((u8)(x)) }

 

The original code contained an expression like this:

 

char buf[1] = {(1,2)};

 

 

using (1,2) can be taken by some compilers as comma expression with a value of 2. But it is obviously not what was intended, I don't think the comma operator is legal in a constant expression in C, I did not look it up though. In C++ the code would be legal (well legal, but still not do what was intended ...).

 

Daniel

在原帖中查看解决方案

0 项奖励
回复
7 回复数
1,874 次查看
Lundin
Senior Contributor IV

A more readable version would be:

 

 

#define x 12345678

#define x0 ((u8)(x >> 24))
#define x1 ((u8)(x >> 16))
#define x2 ((u8)(x >>  8))
#define x3 ((u8)(x      ))


const tIDheader IDheader =
{
  {x0, x1, x2, x3},
  {'A','0'}
};

 

0 项奖励
回复
1,874 次查看
bigmac
Specialist III

Hello,

 

Even though either style of macro solution gives the intended outcome, I notice that a couple of C2705 compiler warning messages are generated with with either approach.  This is for "Possible loss of data", which in this case is not of any consequence.  However, attempts to eliminate the warning (other than globally inhibiting them) have failed.

 


Lundin wrote:

#define x 12345678

#define x0 ((u8)(x >> 24))
#define x1 ((u8)(x >> 16))
#define x2 ((u8)(x >>  8))
#define x3 ((u8)(x      ))

const tIDheader IDheader =
{
  {x0, x1, x2, x3},
  {'A','0'}
};

 


Using Lundin's approach, I can identify that a warning is associated with each of the x2 and x3 macros, but not the x0 and x1 macros.  The x value is obviously a 32 bit quantity, so there is no ambiguity here.

 

I am curious as to the cause of the warnings.

 

Regards,

Mac

 

 

0 项奖励
回复
1,874 次查看
CrasyCat
Specialist III

Hello

 

What is the type associated with tIDheader?

 

CrasyCat

0 项奖励
回复
1,874 次查看
bigmac
Specialist III

Hello CrasyCat,

 

The OP defined the following types -

 

typedef unsigned char u8;

typedef struct {

  u8 partnumber[4];

  u8 version[2];

} tIDheader;

 

 

Regards,

Mac

 

0 项奖励
回复
1,874 次查看
bigmac
Specialist III

Hello,

 

Another issue, not connected with the macro, but with the structure initialisation, is that the null termination byte associated with the string has not been allowed for within the second structure element.  This results in a compiler warning, but the expected result occurs.  To avoid this warning, perhaps the following should be used.

 

const tIDheader IDheader = {

  Mk4Bytes(12345678),

  {'A','0'}

};

 

 

Regards,

Mac

 

0 项奖励
回复
1,875 次查看
CompilerGuru
NXP Employee
NXP Employee

The provided macro contains one pair of braces too much .

Try:

 

 

#define Mk4Bytes(x) { ((u8)((x) >> 24)) , ((u8)((x) >> 16)) , ((u8)((x) >> 8)) , ((u8)(x)) }

 

The original code contained an expression like this:

 

char buf[1] = {(1,2)};

 

 

using (1,2) can be taken by some compilers as comma expression with a value of 2. But it is obviously not what was intended, I don't think the comma operator is legal in a constant expression in C, I did not look it up though. In C++ the code would be legal (well legal, but still not do what was intended ...).

 

Daniel

0 项奖励
回复
1,874 次查看
rlw
Contributor I

Thanks.

 

0 项奖励
回复