Syntax for union parameter

R

Rick C. Hodgin

I appreciate everyone's input. I don't expect anyone to use RDC. As
I have said in another thread, people will come to RDC from the inside
out, not the outside in. I will not be able to convince people to use
RDC, but those people who do use it will have been drawn to use it by
its many features and design, and will in no small part be drawn by
their foundational relationship with Jesus Christ, as I am doing what
I am doing for Him, and for those He brings to the project to contribute
and/or use. This extends out to all of my projects at:

https://github.com/RickCHodgin/

As for the rest of the people on the Earth, there are many many compilers
to choose from that work as you are used to programming. I wish each
of you well on one of those.

May the Lord grant you peace in your hearts, love abounding, and joy
overflowing, as He replaces the angst of a life lived apart from Him
with the new hope found only as citizens of His everlasting Kingdom.

If anyone would like to contact me, click the "main site" link on this
page, and my email is on the upper-left:

http://www.visual-freepro.org/

Or on this page, click "main site" and I'm on the main page:

http://www.libsf.org/

Take care.

Best regards,
Rick C. Hodgin
 
K

Keith Thompson

BartC said:
No, I'm suggesting not having to sit down and write the separate declaration
yourself; it would be automatic.

Ok, that invalidates a lot of of what I wrote.
Sure; for a system which is very close to C, or which is implemented on top
of current C (C99, C11 etc) the header file would still exist, it's just
that *no-one has to manually create it*.

I mean, it can't be the most difficult programming task to scan a .c source
file, pick up the function declarations that are exported (the ones without
a static attribute), and write out those declarations to a .h file, but
sticking a ";" at the end of each instead of having "{" there.

If function declarations were the only things needed in header files,
that would be great. What about type definitions? Macro definitions?

Suppose you have a file "stdio.c" that has definitions for all the C
standard I/O functions. How would your tool know to add a typedef for
`FILE` when it generates "stdio.h"?
Because gmp.h will be distributed by the writers/maintainers of the library.
If the source changes, then they provide a new gmp.h, and a new binary. Of
course, since it is an external library, you will have no knowledge of
exactly how that gmp.h file came into existence, and will not care. (And for
all you know, perhaps various tools have already been used to put it
together.)

(A scheme as I've suggested works best where source modules have a simple
dependency tree, as happens when you have external libraries which are not
going to directly call your code. It doesn't work well when module A calls
functions in B, and module B calls functions in A.

Also, if there are changes to many modules at the same time, then you might
need to be careful in which order they are compiled, although this can be
also be automated. So there are some difficulties, but as I said elsewhere,
since I implemented my scheme in 2012, I can hardly remember having to worry
about prototypes in headers.)


When you recompile a module, it updates the associated header file.

So I recompile recompile gmp.c, and gmp.h is automatically updated. Now
gmp.h has a new timestamp, even though it hasn't actually changed, and
when I type "make" it unnecessarily recompiles every source file that
depends on that header.

The update would have to first regenerate gmp.h as a temporary file,
then update the actual gmp.h only if it doesn't match the temporary
file. Which is certainly doable.
No, it isn't. Easier to implement perhaps, but then the onus is on somebody
(you or me) to make sure the declarations correctly track any changes in the
definition file.

I certainly have no problem using automated tools to (help) generate
header files. Such a tool can't do 100% of the job (unless perhaps it
pays attention to extra annotations in the input source file).

I don't think changing the language to support this would be a good
idea; as long as your tool can work within the language as it's defined
now, why bother?

For most C projects, header files are maintained manually (perhaps with
some automated assistance), and any mismatches between a function
definition and the corresponding declaration are caught immediately on
recompilation. I don't find the copy-and-paste step of just a line or
so for each function to be enough of a burden to worry about.

And if I were going to change the language to handle this better, I'd
probably want to define an actual module system of some sort rather than
adding a layer on top of the existing convention of .h and .c files.
 
S

Seebs

I could write a better editor, but wouldn't it be better to just fix the
language? Certainly, there is no reason in 2014 for separate local function
forward prototype declarations (just to make it clear what I mean!) to be
necessary.

There's two separate issues. One is the utility of prototypes for functions
which you aren't going to define in this file, one is the need to have the
prototypes declared prior to the calls. These aren't directly connected, but
the existence of the former created a reason for there to be a mechanism for
prototyping, and it's not obvious that it's worth much if any effort to have
a way to bypass that mechanism that's only usable in a special case.

The other thing, from my own experience, is: Prototype and function
mismatches are ECC bits for me.

-s
 
B

BartC

Keith Thompson said:
If function declarations were the only things needed in header files,
that would be great. What about type definitions? Macro definitions?

I have an advantage in that my scheme works on a somewhat different
language, so that I can change a few things in a way that doesn't interfere
with how C works now. You'd need to tread more carefully in changing C
itself because header files and so on work a certain way (see below)/

But anyway, type definitions, enums, variable definitions (and named
constants) can all have a global attribute and be exported in the same way
as functions. (My macros are a little different, they are expanded
internally and never exported to C.)
Suppose you have a file "stdio.c" that has definitions for all the C
standard I/O functions. How would your tool know to add a typedef for
`FILE` when it generates "stdio.h"?

? How does FILE get created now?
So I recompile recompile gmp.c, and gmp.h is automatically updated. Now
gmp.h has a new timestamp, even though it hasn't actually changed, and
when I type "make" it unnecessarily recompiles every source file that
depends on that header.

The update would have to first regenerate gmp.h as a temporary file,
then update the actual gmp.h only if it doesn't match the temporary
file. Which is certainly doable.

Yes, it's very easy. A couple lines of in a scripting language.
And if I were going to change the language to handle this better, I'd
probably want to define an actual module system of some sort rather than
adding a layer on top of the existing convention of .h and .c files.

A module system would be better (although I suspect it would have the same
problems of mutual imported files as I've encountered).

But what would be feasible now would be:

(1) Allow function definitions in any order in a source file; there is no
real reason not to have this.

(2) Have a compiler option to write out exported functions to a file
(perhaps something like this already exists in some compiler or other).

This could be a ".h" header file, and it could decide to concern itself
solely with functions; variables, types, macros that the declarations might
also need, can be dealt with conventionally (in a manual header that might
include the automatic one).

(3) Perhaps go a bit further and write out exported file-scope variables
too. This can have the advantage that a definition like this:

int table[] = {10,20,30,40,50};

might be generated in the header file as:

extern int table[5];

which provides useful array dimension info that is otherwise awkward to
impart to another module.

Typedefs and macros, which do not involve actual code or data, can anyway
already be shared without writing two versions, by putting the one
definition in the right header. (However this is not quite as tidy as my
scheme where you share a type defined anywhere in a module, just by putting
'global' in front.)
 
K

Keith Thompson

BartC said:
? How does FILE get created now?

Probably manually. On my system, /usr/include/stdio.h is 944 lines
long; the definition of FILE is

typedef struct _IO_FILE FILE;

where _IO_FILE is defined in some other header that it includes,
directly or indirectly. <stdio.h> is a particulary nasty case; it's
full of system-specific stuff that's not intended for human readers.

[snip]
But what would be feasible now would be:

(1) Allow function definitions in any order in a source file; there is
no real reason not to have this.

Of course function definitions can already be in any order in a source
file. To restate what I think you mean, you'd keep the current rule
that a function definition but you'd change the scope of a function
declaration (whether it's part of a definition or separate). Currently
the scope extends from the point of the declaration to the end of the
translation unit. You'd have the scope extend to the entire translation
unit.

That's for declarations at file scope. For local function declarations
(which IMHO are rarely useful, but they're certainly valid) I presume
the scope would cover the entire enclosing compound statement -- or I
suppose they could be left the way they are.

That would require a compiler to do some sort of pre-pass over the
translation unit to collect function declarations. I don't know how
much work that would impose on compiler developers; it *might* be
substantial.
(2) Have a compiler option to write out exported functions to a file
(perhaps something like this already exists in some compiler or other).

This could be a ".h" header file, and it could decide to concern itself
solely with functions; variables, types, macros that the declarations might
also need, can be dealt with conventionally (in a manual header that might
include the automatic one).

I don't know that that needs to be a compiler option. A tool that can
parse C source could do the job. And a separate tool could be used with
any compiler.
(3) Perhaps go a bit further and write out exported file-scope variables
too. This can have the advantage that a definition like this:

int table[] = {10,20,30,40,50};

might be generated in the header file as:

extern int table[5];

which provides useful array dimension info that is otherwise awkward
to impart to another module.

Typedefs and macros, which do not involve actual code or data, can anyway
already be shared without writing two versions, by putting the one
definition in the right header. (However this is not quite as tidy as my
scheme where you share a type defined anywhere in a module, just by putting
'global' in front.)
 
I

Ike Naar

So I recompile recompile gmp.c, and gmp.h is automatically updated. Now
gmp.h has a new timestamp, even though it hasn't actually changed, and
when I type "make" it unnecessarily recompiles every source file that
depends on that header.

It's not the end of the world, cpu time is cheap nowadays;
and it will happen only once per update of gmp.c (or other .c file),
given a decent build tool.

Manually updating gmp.h (when necessary) also takes time, perhaps even
more time than time that is wasted on automatic rebuilds.
 
R

Rick C. Hodgin

When you recompile a module, it updates the associated header file.
So I recompile recompile gmp.c, and gmp.h is automatically updated. Now
gmp.h has a new timestamp, even though it hasn't actually changed, and
when I type "make" it unnecessarily recompiles every source file that
depends on that header.

The solution is a comparison against the existing file contents. The newly
generated file is only written if anything's changed.

Best regards,
Rick C. Hodgin
 
K

Keith Thompson

Rick C. Hodgin said:
The solution is a comparison against the existing file contents. The newly
generated file is only written if anything's changed.

Which I said in the following paragraph, which you snipped.

And please don't delete attribution lines.
 
R

Rick C. Hodgin

Which I said in the following paragraph, which you snipped.

Keith, why did you include the part about unnecessary recompiles when
you also saw the immediate and obvious solution which completely
negates any need for unnecessary recompiles in the first place?

Best regards,
Rick C. Hodgin
 
B

BartC

Keith Thompson said:
Of course function definitions can already be in any order in a source
file. To restate what I think you mean, you'd keep the current rule
that a function definition but you'd change the scope of a function
declaration (whether it's part of a definition or separate). Currently
the scope extends from the point of the declaration to the end of the
translation unit. You'd have the scope extend to the entire translation
unit.

Sorry, I don't get any of that.
That's for declarations at file scope. For local function declarations
(which IMHO are rarely useful, but they're certainly valid) I presume
the scope would cover the entire enclosing compound statement -- or I
suppose they could be left the way they are.

Nor that (clearly we're at cross-purposes).
That would require a compiler to do some sort of pre-pass over the
translation unit to collect function declarations. I don't know how
much work that would impose on compiler developers; it *might* be
substantial.

That's starting to make sense. Let me illustrate the problem:

void fna(void); /* forward declaration */

int main (void){
fna();
}

void fna(void){
}

To compile this without errors, I need to include the forward declaration.
I'm saying this should not be necessary (nor should it be necessary for me
to arrange the functions in some convoluted order so that a function is
always defined ahead of any calls to it. I should have the freedom to put
functions anywhere, to copy & paste to and from anywhere else, etc, without
worrying about relative ordering or having to drag forward declarations
along with them).

And to clarify further, I'm concerned here with local (ie. non-exported)
functions, so imagine there's a 'static' in front of those declarations.
(I'm still trying to get my head around C exporting any file-scope function
or variable by default, instead of the other way around.)

As for the extra compiler effort involved: I'm fairly certain they already
do enough passes to make this possible, and they're just adopting this
annoying behaviour for compatibility reasons.
I don't know that that needs to be a compiler option. A tool that can
parse C source could do the job. And a separate tool could be used with
any compiler.

Yes, it can, but should it? A tool that parses C is already half a compiler,
including implementing a full pre-processor, but would need to recognise any
special attributes used by the main compiler, as well duplicating the same
set of options passed to the main one.

Effectively you're saying someone not happy with a compiler, should use
their own better one! So why not just fix the original?
 
J

James Kuyper

Sorry, I don't get any of that.

That's too vague a complaint to allow a useful response. I've tried to
figure out an alternate way of explaining what Keith just explained -
all I've been able to come up with are minor variations in the wording.
You should explain more precisely the aspects of what he's saying that
confuse you.
 
B

BartC

James Kuyper said:
That's too vague a complaint to allow a useful response. I've tried to
figure out an alternate way of explaining what Keith just explained -
all I've been able to come up with are minor variations in the wording.
You should explain more precisely the aspects of what he's saying that
confuse you.

Reading it more carefully, I can now see what is being said. Except my issue
didn't seem to have anything to do with scope, since we're talking about
file-scope which you might expect spans the entire file.

I can't see any advantage in limiting scope to only after the point of
declaration, and not before (if we're talking about exactly the same scope
level). And that doesn't seem to affect goto labels, otherwise you could
only jump backwards!

Also, it's not just calls to functions that could refer to forward ones; you
might want some file-scope data which is initialised to function-pointers;
you don't want this stuff at the end of a file or hidden between two
functions.
 
E

Eric Sosman

Reading it more carefully, I can now see what is being said. Except my
issue didn't seem to have anything to do with scope, since we're talking
about file-scope which you might expect spans the entire file.

... which it doesn't. In C as it stands, an file-scope
identifier's scope is not the entire file but the tail of the
translation unit, from the point of declaration to the end.
Your proposal amounts to making a "late" declaration visible
"early" -- which is to say, you suggest that the identifier's
scope should be the entire T.U. and not just the tail. Your
proposal, in other words, is *entirely* about scope.
I can't see any advantage in limiting scope to only after the point of
declaration, and not before (if we're talking about exactly the same
scope level). And that doesn't seem to affect goto labels, otherwise you
could only jump backwards!

An interesting thing about labels is that their nature can
be deduced without the need for a declaration. When the compiler
sees `goto blazes;' it knows immediately that `blazes' can only
be a statement label; you needn't say so. Also, a label's sole
attributes are its label-ness and the statement it designates;
there's no need to specify whether it's `unsigned' or `const'
(or `volatile' -- now, *there's* a dizzying idea!). In short,
labels aren't declared at all (the Standard does not use the
words "declare" or "declaration" in connection with labels),
so analogies between labels and declarable items are suspect.
 
J

James Kuyper

Reading it more carefully, I can now see what is being said. Except my issue
didn't seem to have anything to do with scope, since we're talking about
file-scope which you might expect spans the entire file.

File scope currently does not span the entire file; it starts at the
point of declaration and continues to the end of the translation unit.
It is precisely that rule which would have to be modified to make what
you're talking about work.
I can't see any advantage in limiting scope to only after the point of
declaration, and not before (if we're talking about exactly the same scope
level). ...

I imagine that the original reason would have been to minimize the
number of passes through the file that are needed. It's been argued that
this is no longer as important with modern compilers as it used to be 30
years ago, and I have no quarrel with that argument.

It's removing the ability to declare an identifier that identifies
something which is defined in a different translation units that worries
me. Automatic extraction of a declaration from the definition requires
that the definition already exist, and be in a form that the compiler
can understand; neither restriction applies under the current rules.
Currently, you can declare an identifier for a function or variable
whose definition has not even been written yet, and which might end up
being written is an entirely different language from C, so long as that
language provides some mechanism for creating C-compatible interfaces.
... And that doesn't seem to affect goto labels, otherwise you could
only jump backwards!

The scope of a label includes the entire function body, as explained in
6.2.1p3. 6.2.1p4 starts off "Every other identifier has scope determined
by the placement of its declaration ...". There are four different rules
for how the placement determines where the scope starts - they are
provide by 6.2.1p7 and p8. For all four rules, the scope always starts
somewhere near the place where that identifier is declared/defined.
Also, it's not just calls to functions that could refer to forward ones; you
might want some file-scope data which is initialised to function-pointers;
you don't want this stuff at the end of a file or hidden between two
functions.

Identifiers for functions and identifiers for function pointer objects
are both covered by the "Any other identifier ..." part of 6.2.1p7; a
change to that clause would therefore affect both (unless the change
itself made a distinction between them).
 
E

Eric Sosman

[...]
labels aren't declared at all (the Standard does not use the
words "declare" or "declaration" in connection with labels),

... but it does use "is declared implicitly" in 6.2.1p3.
Sorry for the mis-statement.
so analogies between labels and declarable items are suspect.

The point stands, though: It's something of a stretch to
argue that there is (or should be) a lot of similarity between
declarations that are explicit and those that cannot be so.
 
N

Noob

Kaz said:
Pop quiz.

Suppose that array int a[] contains { 1, 2, 3 }, and int i is 0.

After the execution of a = a[i++], what should be the values in a[]?

Why?


I think a[0] contains 'U' and a[1] contains 'B'.
 
R

Robbie Brown

I again apologize for my ignorance with regards to what is C and
what is C++, or what is a C standard, and what is an extension
as per Microsoft's extensions in Visual C++.

Pop quiz.

Suppose that array int a[] contains { 1, 2, 3 }, and int i is 0.

After the execution of a = a[i++], what should be the values in a[]?

Why?


Well I'm new here so I fully expect I'm setting myself up for some kind
of 'humorous aside' but ...

[i++] no change, postfix increment operator

however

[++i] also no change. prefix increment operator ... but ... but ... %-}
 
J

James Kuyper

I again apologize for my ignorance with regards to what is C and
what is C++, or what is a C standard, and what is an extension
as per Microsoft's extensions in Visual C++.

Pop quiz.

Suppose that array int a[] contains { 1, 2, 3 }, and int i is 0.

After the execution of a = a[i++], what should be the values in a[]?

Why?


Well I'm new here so I fully expect I'm setting myself up for some kind
of 'humorous aside' but ...

[i++] no change, postfix increment operator

however

[++i] also no change. prefix increment operator ... but ... but ... %-}


Your answer leaves me uncertain whether or not you understood the point
Kaz was making. Explaining a joke ruins the joke, so I apologize for the
following.

"If a side effect on a scalar object is unsequenced relative to either a
different side effect on the same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined."
(6.5p2)

i++ has the side-effect of incrementing the value of the scalar object
i. Determining the value of i in a requires performing a value
computation using the value of that same scalar object. There are no
sequence points in that expression, and neither of the two
sub-expressions involving i is a sub-expression of the other, so they
are unsequenced relative to each other. Therefore, the behavior is
undefined.

As a result, there is no such thing as any particular values that
"should be" in a[]. It could contain any values whatsoever, include 3.21
or "'a' no longer has the type int[3]".
 
R

Robbie Brown

I again apologize for my ignorance with regards to what is C and
what is C++, or what is a C standard, and what is an extension
as per Microsoft's extensions in Visual C++.

Pop quiz.

Suppose that array int a[] contains { 1, 2, 3 }, and int i is 0.

After the execution of a = a[i++], what should be the values in a[]?

Why?


Well I'm new here so I fully expect I'm setting myself up for some kind
of 'humorous aside' but ...

[i++] no change, postfix increment operator

however

[++i] also no change. prefix increment operator ... but ... but ... %-}


Your answer leaves me uncertain whether or not you understood the point
Kaz was making. Explaining a joke ruins the joke, so I apologize for the
following.


Of course I didn't understand it, obviously (!)

Interesting 'sense of humor' though.

In Java

public static void main(String args[]){
int a[] = {1, 2, 3};
int i = 0;

a = a[i++];
System.out.print(a[0]);
}

prints 1

whereas

a = a[++i];
System.out.print(a[0]);

prints ... yep, 2.

Now why, given the semantics of the pre and postfix increment operators
should I have expected anything different in C. The semantics are the
same but in C the results are 'undefined'
"If a side effect on a scalar object is unsequenced relative to either a
different side effect on the same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined."
(6.5p2)

i++ has the side-effect of incrementing the value of the scalar object
i. Determining the value of i in a requires performing a value
computation using the value of that same scalar object. There are no
sequence points in that expression, and neither of the two
sub-expressions involving i is a sub-expression of the other, so they
are unsequenced relative to each other. Therefore, the behavior is
undefined.

As a result, there is no such thing as any particular values that
"should be" in a[]. It could contain any values whatsoever, include 3.21
or "'a' no longer has the type int[3]".


One can only assume that this apparent reluctance to cause a compiler to
indicate when something is or maybe undefined is a result of the
apparent ethos of the C community that doing such a thing would impinge
on the freedom of the individual to do anything they like regardless of
how stupid it may be.

Fascinating stuff...
 
R

Robbie Brown

I again apologize for my ignorance with regards to what is C and
what is C++, or what is a C standard, and what is an extension
as per Microsoft's extensions in Visual C++.

Pop quiz.

Suppose that array int a[] contains { 1, 2, 3 }, and int i is 0.

After the execution of a = a[i++], what should be the values in a[]?

Why?


Well I'm new here so I fully expect I'm setting myself up for some kind
of 'humorous aside' but ...

[i++] no change, postfix increment operator

however

[++i] also no change. prefix increment operator ... but ... but ... %-}


Your answer leaves me uncertain whether or not you understood the point
Kaz was making. Explaining a joke ruins the joke, so I apologize for the
following.


Here's another thing.

Let's imagine that I didn't understand what a sequence point is.
Actually I didn't but wikipedia explained it in common English rather
than some incomprehensible technobabble and now I do.

The reason that i=i++ is undefined in C is because the language
definition doesn't (apparently) specify one of the possible behaviors
preferring instead to leave it undefined. What possible reason could
there be for this? It's a well known and understood paradigm in other
languages but apparently not in C.

But I've learned something, which is the whole object of the exercise so
all I can say is 'result'
 

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,573
Members
47,205
Latest member
ElwoodDurh

Latest Threads

Top