Syntax for union parameter

E

Eric Sosman

]
There are many contexts where you're prohibited from defining an
identifier that starts with '_'. This is NOT one of those contexts.
However, can you tell me precisely when it is safe to define such an
identifier? If not, I recommend avoiding them entirely, at least until
you've had time to memorize the relevant rules (section 7.1.3 of the C
standard).
I use them in all cases like this, and for global constants. All constants
in my systems are prefixed with an underscore, and are all caps. It's a
convention I picked up from my assembly days and have just kept.

So *all* your constants infringe on reserved name space?
How very jolly ...

Reserved in C/C++. My target is not C/C++, but RDC. It has been my target
since the mid-90s. I just haven't gotten there yet.
Also, the fact that you did things one way in assembly
language -- or in Java or Ada or PL/I or COBOL -- is not a
good reason to do things the same way in C or Lisp or Fortran
or Lua or Perl.

If not ... what is a good reason (given the constraints of: (1) it is
allowed today by the compiler, (2) it does not cause any issue with my
code in source or executable form, (3) my goals are RDC and not C/C++,
and (4) it becomes part of a standard throughout the toolchain
(anything with an underscore and all caps is a constant, and anything
with an underscore indicates it's not the real thing, but a reference
to something else as through a union))?

(1) "Allowed today" does not imply "allowed tomorrow." In
particular, you needn't change the compiler even one little bit
to get into trouble: Just #include a header you didn't use before,
and all of a sudden the fertilizer hits the fan.

(2) If your identifiers conflict with those used by the
implementation, there might be no effect on the executable: If
the source doesn't compile, there's no executable for it to affect.
On the other hand, the source might compile anyhow, but produce
an executable that is defective or behaves in mysterious ways.

(3) Discussing RDC in a C forum makes as much sense as
discussing Algol in an Esperanto forum.

(4) A toolchain that cannot deal properly with the languages
in use is not a tool, just a chain.
 
B

Ben Bacarisse

Rick C. Hodgin said:
I have had occasion where I've needed to do something like this:
struct SBGRA
{
unsigned char blu;
unsigned char grn;
unsigned char red;
unsigned char alp;
};

The standard allows an implementation to insert arbitrary padding
between members of a struct. This is extremely unlikely when the members
are all of character type, because there's no possibility of alignment
issues that would require padding. However, since your code absolutely
depends upon the absence of such padding, you really should be using a C
construct which actually forbids padding, such as unsigned char[4],
rather than a struct.

I always use whatever compiler setting is required to align everything to
bytes.

You might have portability issues then. Certainly older ARM processors
(you cite ARM as an example) don't like arbitrary alignments. The new
ones might sill for types, but I don't know. In general, I think it's
better to write C without such settings, and to check, with an assert
(static or otherwise), that the structure is the size you expect.

Also, keep in mind that software often lives longer than hardware. You
can't be sure what architectures will be important to you during the
lifetime of a large piece of software.

I use them in all cases like this, and for global constants. All constants
in my systems are prefixed with an underscore, and are all caps. It's a
convention I picked up from my assembly days and have just kept.

Those are "reserved for any use". Using trailing underscore instead is
always safe (thought you still have be take care with the first part of
the name).

[...] In particular, there's
the big-endian/little-endian issue. If you need to port this code
between big-endian and little-endian machines, you'll need to decide
whether the byte order imposed by u.color or the bit order of u._color
is more important. I would expect the byte order of u.color is the
relevant one, and I'll use that assumption below.

My targets are x86 and ARM. They both support little endian. I doubt I
will ever support a big endian machine.

Is ARM not one of those bi-endian CPUs that needs support from its
surrounding chip set to be one or other endian? This is a vague memory
and I may be wrong, but if not there might be ARM systems that are
big-endian "in hardware" and can't be switched.
And if I do, there are handful
of places where I can modify my code IF AND WHEN that ever happens.

That can be a right pain. At the very least, I think it's a good idea
to flag up endian assumptions during writing because finding them all
later can be tricky.

<snip>
 
R

Rick C. Hodgin

My purposes in referencing RDC are to explain, when asked, why I personally
do not use C standards.

Once, when I was in England, and we left the house at 7am local time (2am
my time) I drove on the wrong side of the road, but only for a few hundred
feet because the people who were with me were screaming "WRONG SIDE! WRONG
SIDE!" The loud unison nature of their chorus (a) woke me up and (b) had
me laughing so hard immediately thereafter that I almost couldn't drive. :)

A funny memory.

Best regards,
Rick C. Hodgin
 
K

Kenny McCormack

Rick C. Hodgin said:
If not ... what is a good reason (given the constraints of: (1) it is
allowed today by the compiler, (2) it does not cause any issue with my
code in source or executable form, (3) my goals are RDC and not C/C++,
and (4) it becomes part of a standard throughout the toolchain
(anything with an underscore and all caps is a constant, and anything
with an underscore indicates it's not the real thing, but a reference
to something else as through a union))?

All good points.

Unfortunately, they fall on deaf ears around here.

What it boils down to is this: If you want (for some reason, although
I can't imagine why) to communicate with the thugs of CLC, then you must
speak their language. If you don't, they will either endlessly nitpick you
about stupid stuff (see below for a list) or end up branding you a "troll"
and ignoring you.

A list of things to avoid in any posted code (or else all you'll get in
response is stupid nitpicks):

1) (incorrectly) Prototyping main.
2) Casting the return value of malloc()
3) Using leading underscores in your variable names.
4) etc, etc
 
R

Rick C. Hodgin

You might have portability issues then. Certainly older ARM processors
(you cite ARM as an example) don't like arbitrary alignments. The new
ones might sill for types, but I don't know. In general, I think it's
better to write C without such settings, and to check, with an assert
(static or otherwise), that the structure is the size you expect.

I understand. The data my compilers generate will be appropriately
aligned for the target hardware. As of my desire and goals, they will
be byte packed (though possibly aligned on a boundary for the start).
I would pursue multiple aligned reads and subsequent bit shifts to
access cross-boundary packed data before I would enforce an alignment
in data however.
Also, keep in mind that software often lives longer than hardware. You
can't be sure what architectures will be important to you during the
lifetime of a large piece of software.
Understood.


Those are "reserved for any use". Using trailing underscore instead is
always safe (thought you still have be take care with the first part of
the name).

I've tried that before. I do not appreciate it.
[...] In particular, there's
the big-endian/little-endian issue. If you need to port this code
between big-endian and little-endian machines, you'll need to decide
whether the byte order imposed by u.color or the bit order of u._color
is more important. I would expect the byte order of u.color is the
relevant one, and I'll use that assumption below.

My targets are x86 and ARM. They both support little endian. I doubt
I will ever support a big endian machine.

Is ARM not one of those bi-endian CPUs that needs support from its
surrounding chip set to be one or other endian? This is a vague memory
and I may be wrong, but if not there might be ARM systems that are
big-endian "in hardware" and can't be switched.

Newer ARM chips can work with either endian. I will not be supporting
older ARM chips. There is a cutoff I have in mind. I don't remember
what it is, but it's a version from mid-2000s.
That can be a right pain. At the very least, I think it's a good idea
to flag up endian assumptions during writing because finding them all
later can be tricky.

Yes. I think I would look for << or >> operators in my code. Those
should be the only place where endian issues arise because as the
compiler author I will always ensure that:

typedef unsigned char u8
struct SBGRA { u8 blu, u8 grn; u8 red; u8 alp; };

....is always loaded the same way regardless of how it's stored in
memory. When it is loaded, it will be in little endian format.

Best regards,
Rick C. Hodgin
 
E

Eric Sosman

My purposes in referencing RDC are to explain, when asked, why I personally
do not use C standards.

Then you're in the wrong newsgroup.
Once, when I was in England, and we left the house at 7am local time (2am
my time) I drove on the wrong side of the road, but only for a few hundred
feet because the people who were with me were screaming "WRONG SIDE! WRONG
SIDE!" The loud unison nature of their chorus (a) woke me up and (b) had
me laughing so hard immediately thereafter that I almost couldn't drive. :)

A funny memory.

Endangering the lives of dozens of perfect strangers is
a funny notion of "funny."
 
R

Rick C. Hodgin

All good points.

Unfortunately, they fall on deaf ears around here.

What it boils down to is this...


Understood. Thank you, Kenny.

Best regards,
Rick C. Hodgin
 
R

Rick C. Hodgin

Then you're in the wrong newsgroup.

My responses are when I'm asked why I do this or that.
Endangering the lives of dozens of perfect strangers is
a funny notion of "funny."

I see your point. It was funny though. It was the loud unison nature
of their shouting. It was almost like a rehearsed chant it was so
perfectly timed. Still makes me laugh thinking about it. :)

Best regards,
Rick C. Hodgin
 
K

Keith Thompson

Rick C. Hodgin said:
On 01/28/2014 08:27 PM, Rick C. Hodgin wrote: [...]
void main(void)

The return type of main must be int. Many text books get this wrong, and
many people write their code accordingly, and as a result many compilers
accept such code - those books and those people are all ignoring what
the C standard says. Those compilers can actually be fully conforming -
the behavior of such a program is undefined, which means it's perfectly
acceptable for the implementation to translate it the way you've
incorrectly assumed it must be translated.. However, a decent compiler
should warn you about this mistake.

I used it only to illustrate. I noticed in one of the coding examples
posted to me a void main(void) declaration. I had been using the ones
I am familiar with int main(int argc, char* argv[]) and it's a lot of
typing. So, for illustration I did the shorter version. :)

"int main(void)" is even shorter, and has the considerable virtue of
being correct. (One could quibble that "void main(void)" isn't exactly
*incorrect*, but it's close enough.)
 
R

Rick C. Hodgin

"int main(void)" is even shorter,

I wasn't aware you could surround function definitions in quotes. Awesome!
and has the considerable virtue of
being correct. (One could quibble that "void main(void)" isn't exactly
*incorrect*, but it's close enough.)

"...isn't exactly incorrect, but it's close enough" can be taken two ways.
:)

Best regards,
Rick C. Hodgin
 
K

Keith Thompson

James Kuyper said:
On 01/28/2014 08:27 PM, Rick C. Hodgin wrote:
...
I used it only to illustrate. I noticed in one of the coding examples
posted to me a void main(void) declaration. I had been using the ones
I am familiar with int main(int argc, char* argv[]) and it's a lot of
typing. So, for illustration I did the shorter version. :)
void main(void)

int main() is even shorter, and unlike void main(), it has defined
behavior on all hosted implementations of C.

`int main(void)` is better (and is still shorter than `void
main(void)`). `int main()` is an old-style definition, which is
an obsolescent feature. (A very strict reading of the standard
implies that `int main()` has undefined behavior, but I don't
believe any C compiler would reject it or handle it in other
than the expected manner. The ANSI C committee surely *intended*
`int main()` to continue to be valid; they just didn't quite say so.)

Using prototypes for all function declarations and definitions,
including the definition of main, is IMHO a good habit.

[...]
This is not the best place to discuss your plans for RDC. Why do you
persist in doing so?

Probably because he continues to get attention here.
 
R

Rick C. Hodgin

Using prototypes for all function declarations and definitions,
including the definition of main, is IMHO a good habit.

To quote Dr. Pulaski, chief medical officer on board the U.S.S. Enterprise
(in the episode entitled "The Measure of a Man," in response to a gift given
to Lt. Commander Data as part of his presumed going away party, by Worf,
who stated that the novel "The Dream of the Fire," by K'Rata, attained its
full stature in the hands of the Klingons), "I couldn't disagree more. But, I'll save that argument for another day."
Probably because he continues to get attention here.

Truthfully, it's been kind of exciting and invigorating. It's like I
stand at the circle, the host quizzing me just before stating, "You are
the weakest link. Good bye," to which I am forced to leave because we
are standing upon the sands of the C shore. :) Still, I've had all of
these ideas twoddling around in my head for a long time and now. It's
good to get some feedback.

I also enjoy the witty repartee ... though not as much as I might otherwise
were it more prevalent from all parties concerned.

Best regards,
Rick C. Hodgin
 
B

Ben Bacarisse

Rick C. Hodgin said:
I use Visual Studio 2008. It knows nothing of C11 syntax and must be
deriving these relaxations from its C++ nature, or Microsoft
allowances.

Ah, that's philosophy. What syntax a compiler knows I leave to you.
What syntax it accepts is more matter of fact, and it appears that this
old compiler accepts this new C11 syntax. A common enough occurrence --
many features got into C after being implemented as extensions.
 
D

David Brown

Ah, that's philosophy. What syntax a compiler knows I leave to you.
What syntax it accepts is more matter of fact, and it appears that this
old compiler accepts this new C11 syntax. A common enough occurrence --
many features got into C after being implemented as extensions.

Anonymous structs or unions within other structs and unions has been
accepted as a gcc extension for ages, and I've seen it on other
compilers too. So this does appear to be a commonly implemented
extension that made it into the standards eventually.
 
R

Rick C. Hodgin

Using prototypes for all function declarations and definitions,
including the definition of main, is IMHO a good habit.

Keith, I've been thinking about this ... how do you conclude that using
prototype definitions is, in all cases, a good idea?

I would argue they have their place, but only their place. In a
modern IDE, and under the N-pass nature of modern compiler theory,
there is no need for any prototyping whatsoever.

Best regards,
Rick C. Hodgin
 
K

Keith Thompson

Rick C. Hodgin said:
I wasn't aware you could surround function definitions in quotes. Awesome!

As I'm sure you're aware, I just used the quotation marks to distinguish
the C code from the surrounding text. I more often use markdown syntax,
surrounding code snippets with backticks.

http://daringfireball.net/projects/markdown/
"...isn't exactly incorrect, but it's close enough" can be taken two ways.
:)

Yes, I was unclear. Saying it's incorrect is close enough. The full
truth is that it has undefined behavior for implementations that do
not explicitly document that they support it, implementation-defined
behavior for implementations that do document it. A conforming
compiler is free to reject `void main(void)` -- and I frankly wish
that more compilers did so, since it would help weed out code that
uses it. See 5.1.2.2.1 in the C standard.
 
K

Keith Thompson

Rick C. Hodgin said:
To quote Dr. Pulaski, chief medical officer on board the
U.S.S. Enterprise (in the episode entitled "The Measure of a Man," in
response to a gift given to Lt. Commander Data as part of his presumed
going away party, by Worf, who stated that the novel "The Dream of the
Fire," by K'Rata, attained its full stature in the hands of the
Klingons), "I couldn't disagree more. But, I'll save that argument for
another day."

That's a very long-winded way of saying practically nothing. If you
have an actual counterargument to my recommendation to use prototypes,
I'd be interested in seeing it; one of us might learn something.
(And it's actually about C.)
 
B

Ben Bacarisse

Rick C. Hodgin said:
Keith, I've been thinking about this ... how do you conclude that using
prototype definitions is, in all cases, a good idea?

I would argue they have their place, but only their place. In a
modern IDE, and under the N-pass nature of modern compiler theory,
there is no need for any prototyping whatsoever.

Ah, another C terminology problem. A function definition may or may not
provide a prototype. If you image a C-like language where forward
declaration is not needed, you are still using prototypes if the
function definitions include the parameter types.

Not using prototypes looks like this:

void f(a)
int a;
{
extern int printf();
printf("%d\n", a);
}

int main() { f(4.2); }

and is universally not missed.
 
K

Keith Thompson

Rick C. Hodgin said:
Keith, I've been thinking about this ... how do you conclude that using
prototype definitions is, in all cases, a good idea?

I would argue they have their place, but only their place. In a
modern IDE, and under the N-pass nature of modern compiler theory,
there is no need for any prototyping whatsoever.

Non-prototype function declarations and definitions are an
obsolescent feature that could be removed in a future edition of
the C standard.

Using non-prototype declarations runs a considerable risk of writing
a function call with the wrong number or type(s) of arguments,
and not having the compiler catch it. Sure, a sufficiently clever
compiler could warn you about it, but it would be foolish to count
on that.

I first learned C before prototypes were added to the language.
When I accidentally wrote a call that passed the wrong number of
arguments to a function, I was horrified that the compiler didn't
diagnose it.

Let's be sure that you know what the word means. A prototype is
a function declaration that specifies the type(s) of the parameters.

I can think of no good reason to use non-prototype declarations
or definitions. (Saving a few characters is not IMHO a good reason.)

Why would you ever want to use a non-prototype function declaration
or definition?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,079
Messages
2,570,574
Members
47,207
Latest member
HelenaCani

Latest Threads

Top