macro evaluation in compiler

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

macro evaluation in compiler

ソリューションへジャンプ
3,056件の閲覧回数
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 解決策
2,056件の閲覧回数
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 返答(返信)
2,056件の閲覧回数
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 件の賞賛
返信
2,056件の閲覧回数
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 件の賞賛
返信
2,056件の閲覧回数
CrasyCat
Specialist III

Hello

 

What is the type associated with tIDheader?

 

CrasyCat

0 件の賞賛
返信
2,056件の閲覧回数
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 件の賞賛
返信
2,056件の閲覧回数
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 件の賞賛
返信
2,057件の閲覧回数
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 件の賞賛
返信
2,056件の閲覧回数
rlw
Contributor I

Thanks.

 

0 件の賞賛
返信