By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,429 Members | 1,751 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,429 IT Pros & Developers. It's quick & easy.

Removing "if (a = b)" warning

P: n/a

Is there a standard way to remove the warning that a C compiler might
produce from the statement:

if (a = b) {}

I don't want to do:

if ((a = b) != 0) {}

Because my "a = b" is actually contained in a macro that might be used
as a statement or as an expression within (for example) an "if"
statement.

If it makes any difference, here's exactly what I'm trying to do. In
order to get around a limitation of a particular C compiler that will
not allow p++ (or any other pointer arithmetic) to work correctly across
64KB boundaries, I have come up with a few macros, one of which is:

#define FARPTR_INC(p) p=(void far *)(((ULONG)(p))+sizeof(*(p)))

Now I can do:

UBYTE far *pb;
UWORD far *pw;
ULONG far *pl;
FARPTR_INC(pb); // Replacement for: pb++; (adds 1 to address)
FARPTR_INC(pw); // Replacement for: pw++; (adds 2 to address)
FARPTR_INC(pl); // Replacement for: pl++; (adds 4 to address)

I can also do:

func(FARPTR_INC(p)); // Replacement for: func(p++);

But if I do:

if (FARPTR_INC(p)) {}

Then I get a warning since the compiler is justifiably taking the view
that I might have missed an equals sign and accidentally turned an
equality comparison into an assignment.

[Please excuse the C++ commenting style in my C code. I know you're all
C purists in c.l.c, and rightly so, but I choose to use C++ comments in
my C code because every C compiler I use (or probably ever will use now)
handles it ;-)
.... oh, and stuff like UBYTE is "#define UBYTE unsigned char" etc.]

Nov 15 '05 #1
Share this Question
Share on Google+
32 Replies


P: n/a
On 2005-10-26, Stephen <sp*******@yahoo.co.uk> wrote:

Is there a standard way to remove the warning that a C compiler might
produce from the statement:

if (a = b) {}

I don't want to do:

if ((a = b) != 0) {}

Because my "a = b" is actually contained in a macro that might be used
as a statement or as an expression within (for example) an "if"
statement.
If it's from a macro the macro should have its own parentheses to avoid
precedence problems anyway, say...
If it makes any difference, here's exactly what I'm trying to do. In
order to get around a limitation of a particular C compiler that will
not allow p++ (or any other pointer arithmetic) to work correctly across
64KB boundaries, I have come up with a few macros, one of which is:

#define FARPTR_INC(p) p=(void far *)(((ULONG)(p))+sizeof(*(p)))
#define FARPTR_INC(p) ((p)=(void far *)(((ULONG)(p))+sizeof(*(p))))

This fits with the traditional way of avoiding the error, which is
to do if((a = b)).

Now I can do:

UBYTE far *pb;
UWORD far *pw;
ULONG far *pl;
FARPTR_INC(pb); // Replacement for: pb++; (adds 1 to address)
FARPTR_INC(pw); // Replacement for: pw++; (adds 2 to address)
FARPTR_INC(pl); // Replacement for: pl++; (adds 4 to address)

I can also do:

func(FARPTR_INC(p)); // Replacement for: func(p++);
no it's not. it replaces func(++p) - you'd need the following macro
for p++:

#define FARPTR_POSTINC(p) (((p)=(void far*)((ULONG)(p)+sizeof \
*(p))), (void far *)((ULONG)(p)-sizeof *(p)))

But if I do:

if (FARPTR_INC(p)) {}

Then I get a warning since the compiler is justifiably taking the view
that I might have missed an equals sign and accidentally turned an
equality comparison into an assignment.

[Please excuse the C++ commenting style in my C code. I know you're all
C purists in c.l.c, and rightly so, but I choose to use C++ comments in
my C code because every C compiler I use (or probably ever will use now)
handles it ;-)
And yet no pointer arithmetic?
... oh, and stuff like UBYTE is "#define UBYTE unsigned char" etc.]


Compiler doesn't handle typedefs either, i take it?
Nov 15 '05 #2

P: n/a
On 2005-10-26, Jordan Abel <jm****@purdue.edu> wrote:
[stuff, see other message]


PS Incidentally, what makes you think you can safely do this? A "far pointer"
may not have an integer representation of which adding to it will result in the
next adjacent memory cell.

incidentally, try

#define PTR_ADD(a,i) (&(a)[i])
#define PTR_SUB(a,i) PTR_ADD(a,-i)
#define PTR_EQP(a,i) ((p)=PTR_ADD(a,i))
#define PTR_EQM(a,i) ((p)=PTR_SUB(a,i))
#define PTR_PPX(p) PTR_EQP(a,1)
#define PTR_MMX(p) PTR_EQM(a,1)
#define PTR_XPP(p) (PTR_PPX(p),PTR_SUB(p,1))
#define PTR_XMM(p) (PTR_MMX(p),PTR_ADD(p,1))

More concise, don't require casting, and retain type-safety.

Incidentally, i'd ditch the crappy compiler if i were you.
Nov 15 '05 #3

P: n/a
On 2005-10-26, Jordan Abel <jm****@purdue.edu> wrote:
On 2005-10-26, Jordan Abel <jm****@purdue.edu> wrote:
[stuff, see other message]

[more stuff]


Incidentally, I say "incidentally" way too much. I read over that twice before
posting it without noticing, too
Nov 15 '05 #4

P: n/a
Stephen wrote:
Is there a standard way to remove the warning that a C compiler might
produce from the statement:

if (a = b) {}

I don't want to do:

if ((a = b) != 0) {}
No *standard* way, since compilers are free to issue whatever warnings
they want. There is a *common* way:
if ((a = b)) { }
Because my "a = b" is actually contained in a macro that might be used
as a statement or as an expression within (for example) an "if"
statement.
I'm sure some others can parse that and make sense of it, but it's
beyond me.
#define FARPTR_INC(p) p=(void far *)(((ULONG)(p))+sizeof(*(p)))
If ULONG is an integral type (unsigned long, I suppose), you may be in
deep doo-doo converting a pointer to it. But I suppose you know your
implementation -- since 'far' and 'ULONG' are otherwise undefined
identifiers here. The details of the macros are unimportant for your
question, since
But if I do:
if (FARPTR_INC(p)) {}
this can be subjected to the same treatment:
if ((FARPTR_INC(p))) {}

Now, it has been reported before that some compilers from Borland do not
respond as wished to these parentheses. While that is not a sign of a
broken compiler (it's free to issue such warnings), ir is annoying.

... oh, and stuff like UBYTE is "#define UBYTE unsigned char" etc.]


You can do that if you wish. I prefer using 'unsigned char' when I mean
'unsigned char'. If the name made this an abstract or opaque type, it
might be a different story, but 'UCHAR' screams rather that the type
should be 'unsigned char.' If you *must* do this, consider a typedef
instead of a #define, though/
Nov 15 '05 #5

P: n/a
In article <sl********************@random.yi.org>, Jordan Abel
<jm****@purdue.edu> writes
If it's from a macro the macro should have its own parentheses to avoid
precedence problems anyway, say...

#define FARPTR_INC(p) ((p)=(void far *)(((ULONG)(p))+sizeof(*(p))))

This fits with the traditional way of avoiding the error, which is
to do if((a = b)).
Thanks for the quick reply.

I haven't tried this on the compiler in question yet (on wrong machine
at moment), but I tried it on another compiler and it doesn't help - it
still complains at: if ((a = b))
func(FARPTR_INC(p)); // Replacement for: func(p++);


no it's not. it replaces func(++p) - you'd need the following macro
for p++:

#define FARPTR_POSTINC(p) (((p)=(void far*)((ULONG)(p)+sizeof \
*(p))), (void far *)((ULONG)(p)-sizeof *(p)))


Ahh, well spotted. I had been starting to wonder how to do
postinc/preinc (but only need one so far) but hadn't spotted that I had
documented my preinc attempt incorrectly.
[Please excuse the C++ commenting style in my C code. I know you're all
C purists in c.l.c, and rightly so, but I choose to use C++ comments in
my C code because every C compiler I use (or probably ever will use now)
handles it ;-)


And yet no pointer arithmetic?


None that cross 64KB boundaries.
... oh, and stuff like UBYTE is "#define UBYTE unsigned char" etc.]


Compiler doesn't handle typedefs either, i take it?


Oh I knew someone would say that ;-)

I've had difficulties in the past with typedef support. I'm sure I could
probably change it to a typedef now though. Old habits die hard.
PS Incidentally, what makes you think you can safely do this? A "far
pointer" may not have an integer representation of which adding to it
will result in the next adjacent memory cell.
These are macros dedicated to a specific compiler/platform. The casting
to ULONG does work, it's the only way around this problem without
resorting to assembler. The macros collapse to regular "p++" statements
on the better platforms.
incidentally, try
#define PTR_ADD(a,i) (&(a)[i])
This, and your other examples, don't work on the affected compiler. The
implementation of [i] might cross a 64KB boundary.
Incidentally, i'd ditch the crappy compiler if i were you.


It's actually highly regarded as the best compiler available for this
platform by far, and it's also the most expensive. The problem is that
its an embedded platform, and flat memory space beyond 64KB is
relatively new on this processor architecture, so compiler support for
the new far (flat) memory is not quite at its best yet.

Any other suggestions for how to stop the warning on: "if (a = b)" ?
Nov 15 '05 #6

P: n/a
On 2005-10-26, Stephen <sp*******@yahoo.co.uk> wrote:
In article <sl********************@random.yi.org>, Jordan Abel
<jm****@purdue.edu> writes
If it's from a macro the macro should have its own parentheses
to avoid precedence problems anyway, say...

#define FARPTR_INC(p) ((p)=(void far *)(((ULONG)(p))+sizeof(*(p))))

This fits with the traditional way of avoiding the error, which
is to do if((a = b)).
Thanks for the quick reply.

I haven't tried this on the compiler in question yet (on wrong
machine at moment), but I tried it on another compiler and it
doesn't help - it still complains at: if ((a = b))
func(FARPTR_INC(p)); // Replacement for: func(p++);


no it's not. it replaces func(++p) - you'd need the following
macro for p++:

#define FARPTR_POSTINC(p) (((p)=(void far*)((ULONG)(p)+sizeof \
*(p))), (void far *)((ULONG)(p)-sizeof *(p)))


Ahh, well spotted. I had been starting to wonder how to do
postinc/preinc (but only need one so far) but hadn't spotted
that I had documented my preinc attempt incorrectly.
[Please excuse the C++ commenting style in my C code. I know
you're all C purists in c.l.c, and rightly so, but I choose
to use C++ comments in my C code because every C compiler I
use (or probably ever will use now) handles it ;-)


And yet no pointer arithmetic?


None that cross 64KB boundaries.


How, precisely, are 'far pointers' represented into unsigned
long? You've said that 64kb boundaries matter - i'd like to see
documentation for your platform
... oh, and stuff like UBYTE is "#define UBYTE unsigned char"
etc.]


Compiler doesn't handle typedefs either, i take it?


Oh I knew someone would say that ;-)

I've had difficulties in the past with typedef support. I'm
sure I could probably change it to a typedef now though. Old
habits die hard.
PS Incidentally, what makes you think you can safely do this? A
"far pointer" may not have an integer representation of which
adding to it will result in the next adjacent memory cell.


These are macros dedicated to a specific compiler/platform. The
casting to ULONG does work, it's the only way around this
problem without resorting to assembler. The macros collapse to
regular "p++" statements on the better platforms.


What i'm saying is that it will NOT work crossing a segment
boundary depending on how far pointers are actually represented.
incidentally, try
#define PTR_ADD(a,i) (&(a)[i])


This, and your other examples, don't work on the affected
compiler. The implementation of [i] might cross a 64KB
boundary.


And yours does not? Regardless, it's still much more readable to
use a single primitive that all your other macros are based on.
if you insist on doing it your way, use

#define PTR_ADD(a,i) ((void far *)((unsigned long)(a)+(i)*sizeof *(a)))

and all my other definitions.

and, perhaps most importantly, guard this definition with an
ifdef for your platform, and use the following for other
platforms:

#define PTR_ADD(a,i) ((a)+(i))

Even if you know your platform has a pointer representation where
the casting is safe, others might not.

also, if your compiler supports a [non-standard] typeof operator,
use it instead of void.
Incidentally, i'd ditch the crappy compiler if i were you.


It's actually highly regarded as the best compiler available
for this platform by far, and it's also the most expensive. The
problem is that its an embedded platform, and flat memory space
beyond 64KB is relatively new on this processor architecture,
so compiler support for the new far (flat) memory is not quite
at its best yet.

Any other suggestions for how to stop the warning on: "if (a =
b)" ?


That was explained in my first post - add a pair of parens
surrounding the macro definition.
Nov 15 '05 #7

P: n/a
In article <Ay****************@newsread3.news.atl.earthlink.n et>, Martin
Ambuhl <ma*****@earthlink.net> writes
Because my "a = b" is actually contained in a macro that might be used
as a statement or as an expression within (for example) an "if"
statement.
I'm sure some others can parse that and make sense of it, but it's
beyond me.


Sorry, my "Because..." line was a continuation of my "I don't want to
do:" line, with the example in the middle.
this can be subjected to the same treatment:
if ((FARPTR_INC(p))) {}

Now, it has been reported before that some compilers from Borland do not
respond as wished to these parentheses. While that is not a sign of a
broken compiler (it's free to issue such warnings), ir is annoying.
Hmm, as you'll see from my other reply this does not work, but
interestingly my quick test was on a Borland compiler. I'll need to get
back to my development machine and try it on the other compiler.
... oh, and stuff like UBYTE is "#define UBYTE unsigned char" etc.]


You can do that if you wish. I prefer using 'unsigned char' when I
mean
'unsigned char'. If the name made this an abstract or opaque type, it
might be a different story, but 'UCHAR' screams rather that the type
should be 'unsigned char.'


I NEVER use integral types throughout the code. It's too non-portable on
cross-platform code. I have come across platforms where char defaults to
32-bit and others where int is 8-bit. Hence the reason I create my own
"types". A UBYTE will be guaranteed 8-bit unsigned regardless of how
hard I have to hit the compiler. It also saves space - the embedded
targets often need other additional compiler specific qualifiers in
declarations and casts so some lines can get a bit long. I've even known
people to use U8, U16 etc. Plus: UBYTE, SBYTE, UWORD, SWORD, ULONG,
SLONG are all the same length (characters) so the code looks pretty :-)
If you *must* do this, consider a typedef instead of a #define, though


Indeed, see my other reply :-)
Nov 15 '05 #8

P: n/a
On 2005-10-26, Stephen <sp*******@yahoo.co.uk> wrote:
I NEVER use integral types throughout the code. It's too non-portable on
cross-platform code. I have come across platforms where char defaults to
32-bit and others where int is 8-bit. Hence the reason I create my own
"types". A UBYTE will be guaranteed 8-bit unsigned regardless of how
hard I have to hit the compiler. It also saves space - the embedded
targets often need other additional compiler specific qualifiers in
declarations and casts so some lines can get a bit long. I've even known
people to use U8, U16 etc. Plus: UBYTE, SBYTE, UWORD, SWORD, ULONG,
SLONG are all the same length (characters) so the code looks pretty :-)


I'd recommend as a stylistic matter against switching between
c-style typenames and asm-style ones. if you must do this, consider
either ?BYTE ?WORD ?DWRD ?QWRD or ?CHAR ?SHRT ?LONG ?LLNG.

incidentally, on all systems where an 8-bit type is even possible at
all, that type will be [signed, unsigned] char.
Nov 15 '05 #9

P: n/a
In article <sl********************@random.yi.org>, Jordan Abel
<jm****@purdue.edu> writes
How, precisely, are 'far pointers' represented into unsigned
long? You've said that 64kb boundaries matter - i'd like to see
documentation for your platform
Trust me, it works on this platform.
What i'm saying is that it will NOT work crossing a segment
boundary depending on how far pointers are actually represented.
It does work across a 64KB boundary on this platform. Converting to
ULONG works. Arithmetic works on ULONG. Converting back to pointer
works.
This, and your other examples, don't work on the affected
compiler. The implementation of [i] might cross a 64KB
boundary.


And yours does not?


Not in pointer land. My addition is in ULONG land, which works. Hence
the reason for temporary conversion to ULONG.
Regardless, it's still much more readable to
use a single primitive that all your other macros are based on.
if you insist on doing it your way, use

#define PTR_ADD(a,i) ((void far *)((unsigned long)(a)+(i)*sizeof *(a)))
You mean using it as: p = PTR_ADD(p,10); ?

Hmmm... I might do that, if it eliminates all possible errors.
That was explained in my first post - add a pair of parens
surrounding the macro definition.


And my reply indicated it didn't work, but as someone pointed out that
might be to do with the compiler I tested it on...
Nov 15 '05 #10

P: n/a
In article <sl********************@random.yi.org>, Jordan Abel
<jm****@purdue.edu> writes
I'd recommend as a stylistic matter against switching between
c-style typenames and asm-style ones. if you must do this, consider
either ?BYTE ?WORD ?DWRD ?QWRD or ?CHAR ?SHRT ?LONG ?LLNG.
Identifiers beginning with ? do not work on at least one of the
compilers I use regularly.
incidentally, on all systems where an 8-bit type is even possible at
all, that type will be [signed, unsigned] char.


In theory perhaps. But embedded compilers don't always meet ANSI
standards and usually deliberately break them for various reasons. I'm
sure one of the DSP environments I used defaulted "unsigned char" to
32-bit but then let you qualify the declaration if you insist on making
it 8-bit. The fun of embedded systems...

Nov 15 '05 #11

P: n/a
On 2005-10-26, Stephen <sp*******@yahoo.co.uk> wrote:
How, precisely, are 'far pointers' represented into unsigned
long? You've said that 64kb boundaries matter - i'd like to see
documentation for your platform


Trust me, it works on this platform.


what platform is it - i would like to see documentation anyway out
of my own curiosity
Regardless, it's still much more readable to
use a single primitive that all your other macros are based on.
if you insist on doing it your way, use

#define PTR_ADD(a,i) ((void far *)((unsigned long)(a)+(i)*sizeof *(a)))


You mean using it as: p = PTR_ADD(p,10); ?

Hmmm... I might do that, if it eliminates all possible errors.


as ((p)=PTR_ADD(p,1)) - which iirc was the text of my PTR_PPX macro.
[PPX stands for "++x"]
That was explained in my first post - add a pair of parens
surrounding the macro definition.


And my reply indicated it didn't work, but as someone pointed out that
might be to do with the compiler I tested it on...


If that doesn't work nothing will. Tell your compiler to shut up
Nov 15 '05 #12

P: n/a
On 2005-10-26, Stephen <sp*******@yahoo.co.uk> wrote:
In article <sl********************@random.yi.org>, Jordan Abel
<jm****@purdue.edu> writes
I'd recommend as a stylistic matter against switching between
c-style typenames and asm-style ones. if you must do this, consider
either ?BYTE ?WORD ?DWRD ?QWRD or ?CHAR ?SHRT ?LONG ?LLNG.


Identifiers beginning with ? do not work on at least one of the
compilers I use regularly.


? as a wildcard meaning in this case S or U.
incidentally, on all systems where an 8-bit type is even possible at
all, that type will be [signed, unsigned] char.


In theory perhaps. But embedded compilers don't always meet ANSI
standards and usually deliberately break them for various reasons. I'm
sure one of the DSP environments I used defaulted "unsigned char" to
32-bit but then let you qualify the declaration if you insist on making
it 8-bit. The fun of embedded systems...


and what is the sizeof(your 8-bit type)? 0.25?
Nov 15 '05 #13

P: n/a
In article <sl********************@random.yi.org>, Jordan Abel
<jm****@purdue.edu> writes
what platform is it - i would like to see documentation anyway out
of my own curiosity


Keil C51 for extended memory architecture 8051s.

The far pointer isn't a native type on the processor. It's essentially
an encapsulated (but documented) implementation for which the compiler
vendor has supplied suitable implementations of stuff like memcpy() etc.
but they don't offer proper support for objects across 64KB boundaries,
including pointer arithmetic across such boundaries.

The pointer is implemented as 24-bit big-endian and contains an offset
to distinguish it from other address spaces.

An address might be stored as: 0xAA 0xBB 0xCC
(although that doesn't correspond to address 0xAABBCC due to the
offset).

Conversion to ULONG would result in: 0x00AABBCC. The offset still exists
here. If you wanted a true ULONG representation of the address you have
to adjust by the offset (yet another macro!).

I do my inc/dec/add/sub on the ULONG to give: 0x00DDEEFF

Conversion back to pointer gives: 0xDD 0xEE 0xFF
You mean using it as: p = PTR_ADD(p,10); ?

Hmmm... I might do that, if it eliminates all possible errors.


as ((p)=PTR_ADD(p,1)) - which iirc was the text of my PTR_PPX macro.


Ahh, I see, you mean use separate macros for assignment and expressions.

I was trying to use one macro for all, but your way is probably the only
way to eliminate the warnings.

Thanks.

Nov 15 '05 #14

P: n/a
In article <sl********************@random.yi.org>, Jordan Abel
<jm****@purdue.edu> writes
On 2005-10-26, Stephen <sp*******@yahoo.co.uk> wrote:
In article <sl********************@random.yi.org>, Jordan Abel
<jm****@purdue.edu> writes
I'd recommend as a stylistic matter against switching between
c-style typenames and asm-style ones. if you must do this, consider
either ?BYTE ?WORD ?DWRD ?QWRD or ?CHAR ?SHRT ?LONG ?LLNG.


Identifiers beginning with ? do not work on at least one of the
compilers I use regularly.


? as a wildcard meaning in this case S or U.


Ahh, sorry, wooosh - missed the point entirely.

Time for some food I think...

I thought you meant prefixing them with ? to distinguish them from BYTE
as used in an assembler. The DWORD hatred is just a personal thing I
guess. I've always preferred LONG. Somehow when I see QWORD I usually
have to stop and think just how big it is, which increases the
likelihood of mistakes. And as for "short", to coin a phrase, how short
is a piece of string? I've seen shorts at 8, 16 or 32 bit and now
completely hate the word short :-)

It should be taken out the back and short (groan...)

Incidentally, did you notice that you didn't use the word incidentally
in that last message?
Nov 15 '05 #15

P: n/a
Stephen wrote:
Is there a standard way to remove the warning that a C compiler might
produce from the statement:

if (a = b) {}

I don't want to do:

if ((a = b) != 0) {}

Because my "a = b" is actually contained in a macro that might be used
as a statement or as an expression within (for example) an "if"
statement. .... I have come up with a few macros, one of which is:

#define FARPTR_INC(p) p=(void far *)(((ULONG)(p))+sizeof(*(p)))


Try:
#define FARPTR_INC(p) (p=(void far *)(((ULONG)(p))+sizeof(*(p))),p)

Thad

Nov 15 '05 #16

P: n/a
Stephen wrote
(in article <4U**************@rtsoft.demon.co.uk>):
The far pointer isn't a native type on the processor. It's essentially
an encapsulated (but documented) implementation for which the compiler
vendor has supplied suitable implementations of stuff like memcpy() etc.
but they don't offer proper support for objects across 64KB boundaries,
including pointer arithmetic across such boundaries.

The pointer is implemented as 24-bit big-endian and contains an offset
to distinguish it from other address spaces.


I just had a flashback to the old AHINCR driver hack in Windows
3.1 when using objects larger than 64KB. Thanks, uh, I think.
:-)
--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw

Nov 15 '05 #17

P: n/a
Stephen <sp*******@yahoo.co.uk> writes:
In article <sl********************@random.yi.org>, Jordan Abel
<jm****@purdue.edu> writes
On 2005-10-26, Stephen <sp*******@yahoo.co.uk> wrote:
In article <sl********************@random.yi.org>, Jordan Abel
<jm****@purdue.edu> writes
I'd recommend as a stylistic matter against switching between
c-style typenames and asm-style ones. if you must do this, consider
either ?BYTE ?WORD ?DWRD ?QWRD or ?CHAR ?SHRT ?LONG ?LLNG.

Identifiers beginning with ? do not work on at least one of the
compilers I use regularly.


? as a wildcard meaning in this case S or U.


Ahh, sorry, wooosh - missed the point entirely.

Time for some food I think...

I thought you meant prefixing them with ? to distinguish them from BYTE
as used in an assembler. The DWORD hatred is just a personal thing I
guess. I've always preferred LONG. Somehow when I see QWORD I usually
have to stop and think just how big it is, which increases the
likelihood of mistakes. And as for "short", to coin a phrase, how short
is a piece of string? I've seen shorts at 8, 16 or 32 bit and now
completely hate the word short :-)


Anyone reading your code is going to assume that LONG means long.
If it does, it's redundant; if it's not, it's misleading.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #18

P: n/a
In article <+l**************@rtsoft.demon.co.uk>,
Stephen <sp*******@yahoo.co.uk> wrote:
Is there a standard way to remove the warning that a C compiler might
produce from the statement:

if (a = b) {}

I don't want to do:

if ((a = b) != 0) {}

Because my "a = b" is actually contained in a macro that might be used
as a statement or as an expression within (for example) an "if"
statement.

If it makes any difference, here's exactly what I'm trying to do. In
order to get around a limitation of a particular C compiler that will
not allow p++ (or any other pointer arithmetic) to work correctly across
64KB boundaries, I have come up with a few macros, one of which is:

#define FARPTR_INC(p) p=(void far *)(((ULONG)(p))+sizeof(*(p)))


God, this is so broken, it is not funny anymore.

On the ancient compilers that I know where incrementing a pointer past a
64 KB boundary didn't work, this code would _definitely_ not work.

Hint: On an x86 in 16 bit mode, the difference between one legal segment
and the next one is not one, but eight.
Nov 15 '05 #19

P: n/a
Christian Bau <ch***********@cbau.freeserve.co.uk> writes:
In article <+l**************@rtsoft.demon.co.uk>,
Stephen <sp*******@yahoo.co.uk> wrote:

[...]
If it makes any difference, here's exactly what I'm trying to do. In
order to get around a limitation of a particular C compiler that will
not allow p++ (or any other pointer arithmetic) to work correctly across
64KB boundaries, I have come up with a few macros, one of which is:

#define FARPTR_INC(p) p=(void far *)(((ULONG)(p))+sizeof(*(p)))


God, this is so broken, it is not funny anymore.

On the ancient compilers that I know where incrementing a pointer past a
64 KB boundary didn't work, this code would _definitely_ not work.

Hint: On an x86 in 16 bit mode, the difference between one legal segment
and the next one is not one, but eight.


The OP isn't using an x86.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #20

P: n/a
In article <christian.bau-01DDA7.21520126102005@slb-
newsm1.svr.pol.co.uk>, Christian Bau <ch***********@cbau.freeserve.co.uk
writes
In article <+l**************@rtsoft.demon.co.uk>,
Stephen <sp*******@yahoo.co.uk> wrote:
If it makes any difference, here's exactly what I'm trying to do. In
order to get around a limitation of a particular C compiler that will
not allow p++ (or any other pointer arithmetic) to work correctly across
64KB boundaries, I have come up with a few macros, one of which is:

#define FARPTR_INC(p) p=(void far *)(((ULONG)(p))+sizeof(*(p)))
God, this is so broken, it is not funny anymore.


Oh for goodness sake. It's NOT broken (or at least the slightly improved
version) in the exactly/only circumstances in which it is being used.
On the ancient compilers that I know where incrementing a pointer past a
64 KB boundary didn't work, this code would _definitely_ not work.

Hint: On an x86 in 16 bit mode, the difference between one legal segment
and the next one is not one, but eight.


I'm not using x86. I believe I made it perfectly clear that this
particular instance of the macro was directly targeted at a specific
platform to get around a specific problem.

You can take your "must be ANSI C compliant" mentality too far when you
forget to engage your brain.
Nov 15 '05 #21

P: n/a
Stephen wrote:
Any other suggestions for how to stop the warning on: "if (a = b)" ?
1) Read your compiler documentation and find a switch that does it.
2) Pass the compiler output through 'grep' and remove the warnings
you don't like.
3) Don't use your macro inside an 'if' statement:
FARPTR_INC(p);
if (p)
{ ...etc
Jordan Abel wrote:
what platform is it - i would like to see documentation anyway out
of my own curiosity
Keil C51 for extended memory architecture 8051s.


IMHO, you should avoid creating objects that cross 64KB boundaries.
Then you would not have any of these problems.
Does the system documentation on the "extended memory architecture"
include any suggestions along these lines?
I've seen shorts at 8, 16 or 32 bit and now completely hate the
word short :-)


An 8-bit short would not conform to the C standard.

Nov 15 '05 #22

P: n/a
In article <11*********************@z14g2000cwz.googlegroups. com>, Old
Wolf <ol*****@inspire.net.nz> writes
3) Don't use your macro inside an 'if' statement:
FARPTR_INC(p);
if (p)
Yes, I've considered using that if I need it.

However, having spent more time today fiddling with macros across
various platforms I've now reached the state where there isn't a problem
any more. The only platform where I need to use this particular horrible
kludge inside an 'if' or 'while' is one that doesn't seem to issue
warnings anyway. It doesn't even issue a warning at 'if (a = b)' which
is a bit disconcerting. Good job the code is multi-platform, you sort of
get the benefits of all of the platforms put together so if I make such
a mistake and one compiler lets me away with it then one of the other
compilers won't.
Keil C51 for extended memory architecture 8051s.


IMHO, you should avoid creating objects that cross 64KB boundaries.


Oh I agree, C allocated objects never cross 64KB boundaries. But in this
case it isn't an "object" in the C sense, because the same problem
occurs on native pointer support (I use pointers to large data areas
that the compiler has no direct knowledge of).
Does the system documentation on the "extended memory architecture"
include any suggestions along these lines?


Sure.

It was one of their macros that I borrowed the cast to ULONG from :-)

But they admit issues with 64KB boundaries for now.
I've seen shorts at 8, 16 or 32 bit and now completely hate the
word short :-)


An 8-bit short would not conform to the C standard.


Nor would half the other stuff I regularly have to deal with in embedded
compilers. See the fun us embedded guys have? Must be terrible only ever
being able to write strict ANSI C code ;-)

Although, seriously, I do admire the depth of knowledge encountered in
here from the C purists. Can someone give me a hyperlink to the official
C standard? It would make a good read from time to time...

Nov 15 '05 #23

P: n/a
Stephen <sp*******@yahoo.co.uk> writes:
[...]
Although, seriously, I do admire the depth of knowledge encountered in
here from the C purists. Can someone give me a hyperlink to the official
C standard? It would make a good read from time to time...


The standard itself is available as a PDF for $18 from ANSI (I don't
have the URL).

A committee draft, n1124.pdf, is freely available; Google will find
it. It includes the C99 standard with some more recent corrections
merged in (and marked with change bars).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #24

P: n/a
Stephen wrote:
Old Wolf <ol*****@inspire.net.nz> writes

IMHO, you should avoid creating objects that cross 64KB boundaries.
Oh I agree, C allocated objects never cross 64KB boundaries. But in
this case it isn't an "object" in the C sense, because the same
problem occurs on native pointer support (I use pointers to large
data areas that the compiler has no direct knowledge of).


You must be using some sort of structure withing these large data
areas -- perhaps you can organize that structure so that you
never need to do pointer arithmetic across a boundary.

(Note that the C compiler is actually conforming to the C standard,
as it is undefined behaviour to use pointers to areas that the
compiler has no direct knowledge of).
An 8-bit short would not conform to the C standard.


Nor would half the other stuff I regularly have to deal with in
embedded compilers. See the fun us embedded guys have? Must be
terrible only ever being able to write strict ANSI C code ;-)


This is different. Usually, embedded compilers support ANSI C
and add their own extensions (such as far pointers, in your case).
An embedded system should be able to compile and run any
strictly conforming ANSI C program.

However, 8-bit short is not an "extension", it would actually
break strictly conforming code.
It would make a good read sometime


Trust me, it is painful to read:)
Try reading the newsgroup FAQ, you can learn most of the points
that come up regularly in this newsgroup (funnily enough).

Nov 15 '05 #25

P: n/a
On 2005-10-27, Old Wolf <ol*****@inspire.net.nz> wrote:
Stephen wrote:
Old Wolf <ol*****@inspire.net.nz> writes
An 8-bit short would not conform to the C standard.


Nor would half the other stuff I regularly have to deal with in
embedded compilers. See the fun us embedded guys have? Must be
terrible only ever being able to write strict ANSI C code ;-)


This is different. Usually, embedded compilers support ANSI C
and add their own extensions (such as far pointers, in your case).
An embedded system should be able to compile and run any
strictly conforming ANSI C program.


What about one that uses "far" as an identifier? To support those,
the compiler would need to require a header that includes #define
far __far to follow the standard.

Stephen, an explanation of _why_ an 8-bit short would be illegal -
short is required to represent at least the range -32767..32767 -
thus it must be at least 16 bits.
Nov 15 '05 #26

P: n/a
Stephen <sp*******@yahoo.co.uk> writes:
Is there a standard way to remove the warning that a C compiler might
produce from the statement:

if (a = b) {}

I don't want to do:

if ((a = b) != 0) {}

Because my "a = b" is actually contained in a macro that might be used
as a statement or as an expression within (for example) an "if"
statement.

If it makes any difference, here's exactly what I'm trying to do. In
order to get around a limitation of a particular C compiler that will
not allow p++ (or any other pointer arithmetic) to work correctly across
64KB boundaries, I have come up with a few macros, one of which is:

#define FARPTR_INC(p) p=(void far *)(((ULONG)(p))+sizeof(*(p)))

Now I can do:

UBYTE far *pb;
UWORD far *pw;
ULONG far *pl;
FARPTR_INC(pb); // Replacement for: pb++; (adds 1 to address)
FARPTR_INC(pw); // Replacement for: pw++; (adds 2 to address)
FARPTR_INC(pl); // Replacement for: pl++; (adds 4 to address)

I can also do:

func(FARPTR_INC(p)); // Replacement for: func(p++);

But if I do:

if (FARPTR_INC(p)) {}

Then I get a warning since the compiler is justifiably taking the view
that I might have missed an equals sign and accidentally turned an
equality comparison into an assignment.


The comment says FARPTR_INC(p) is a replacement for p++, but
the way the macro definition is written, FARPTR_INC(p) looks
more like ++p. Presumably the macro definition is what's
actually desired, in which case the comment should be changed.
Also INC_FARPTR() might be a better name than FARPTR_INC() for
the pre-increment semantics.

Usually it's good to enclose macro definitions (when intended
to serve as expressions) in parentheses. The macro FARPTR_INC
is supposed to be usable as an expression or sub-expression,
so its definition should be enclosed in parentheses. If this
is done then

if( FARPTR_INC(p) != 0 ) ...

will work just fine.
And now, what everyone has been waiting for: the Top 10 List
of ways to avoid warnings for 'if( a = b )'...

(...drum roll...)
10. a = b;
if( a ) ...
9. if( (a = b) ) ...
8. #define NONZERO(x) ((x) != 0)
if( NONZERO( a = b ) ) ...
7. if( a = b, a ) ...
6. if( !! (a = b) ) ...
5. #define ASSIGN(a,b) ((a) = (b))
if( ASSIGN(a,b) ) ...
4. if( (_Bool) (a = b) ) ...
3. if( 0 || (a = b) ) ...
2. if( 1? a = b :0 ) ...
And now the number 1 way to avoid warnings on 'if( a = b )'...

1. #define if(x) if( (x) )
if( a = b ) ...
Nov 15 '05 #27

P: n/a
Stephen <sp*******@yahoo.co.uk> wrote:
You can take your "must be ANSI C compliant" mentality too far when you
forget to engage your brain.


Are you the ghost of Dan Pop? What have you done with him?

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 15 '05 #28

P: n/a
Martin Ambuhl wrote:

Stephen wrote:
Is there a standard way to remove
the warning that a C compiler might
produce from the statement:

if (a = b) {}

I don't want to do:

if ((a = b) != 0) {}


No *standard* way, since compilers are free to issue whatever warnings
they want. There is a *common* way:
if ((a = b)) { }
Because my "a = b" is actually contained
in a macro that might be used
as a statement or as an expression within (for example) an "if"
statement.


I'm sure some others can parse that and make sense of it, but it's
beyond me.


I can't.

if (A)
means exactly the same thing as
if ((A) != 0)

for any and all possible meanings of A, including funky macros.

--
pete
Nov 15 '05 #29

P: n/a
pete <pf*****@mindspring.com> writes:
if (A)
means exactly the same thing as
if ((A) != 0)

for any and all possible meanings of A, including funky macros.


Here's an interesting funky macro to go along with that
observation:
#define if(expr) if ((expr) != 0)
(Does it break anything?)
--
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Nov 15 '05 #30

P: n/a
In article <43***********@mindspring.com>, pete <pf*****@mindspring.com>
writes
Martin Ambuhl wrote:

Stephen wrote:
> Is there a standard way to remove
> the warning that a C compiler might
> produce from the statement:
>
> if (a = b) {}
>
> I don't want to do:
>
> if ((a = b) != 0) {}
if (A)
means exactly the same thing as
if ((A) != 0)

for any and all possible meanings of A, including funky macros.


You've missed the point:

if ((a = b) != 0)

will kill the warning generated by:

if (a = b)

Nov 15 '05 #31

P: n/a
Ben Pfaff wrote:
pete <pf*****@mindspring.com> writes:
if (A)
means exactly the same thing as
if ((A) != 0)

for any and all possible meanings of A, including funky macros.


Here's an interesting funky macro to go along with that
observation:
#define if(expr) if ((expr) != 0)
(Does it break anything?)


It can if you include a standard header after the macro
definition. Also, if A is an expression that includes a non-
parenthesised comma, then there is a problem since the macro
only takes one parameter.

--
Peter

Nov 15 '05 #32

P: n/a
Stephen wrote:

In article <43***********@mindspring.com>, pete <pf*****@mindspring.com>
writes
Martin Ambuhl wrote:

Stephen wrote:
> Is there a standard way to remove
> the warning that a C compiler might
> produce from the statement:
>
> if (a = b) {}
>
> I don't want to do:
>
> if ((a = b) != 0) {}
if (A)
means exactly the same thing as
if ((A) != 0)

for any and all possible meanings of A, including funky macros.


You've missed the point:


That happens more often than I like.
if ((a = b) != 0)

will kill the warning generated by:

if (a = b)


I thought that you wanted to kill the warning.

if ((a = b) != 0) {}
kills the warning very nicely
without changing the meaning of the code.

--
pete
Nov 15 '05 #33

This discussion thread is closed

Replies have been disabled for this discussion.