Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #103352 > unrolled thread

How to compile several C files

Started byAlla _ <modelling.data@gmail.com>
First post2017-02-07 06:10 -0800
Last post2017-02-07 19:02 +0100
Articles 20 on this page of 80 — 18 participants

Back to article view | Back to comp.lang.c


Contents

  How to compile several C files Alla _ <modelling.data@gmail.com> - 2017-02-07 06:10 -0800
    Re: How to compile several C files Malcolm McLean <malcolm.mclean5@btinternet.com> - 2017-02-07 07:02 -0800
    Re: How to compile several C files David Brown <david.brown@hesbynett.no> - 2017-02-07 16:03 +0100
    Re: How to compile several C files Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-07 15:06 +0000
      Re: How to compile several C files BartC <bc@freeuk.com> - 2017-02-07 15:14 +0000
        Re: How to compile several C files Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-07 16:02 +0000
      Re: How to compile several C files Richard Heathfield <rjh@cpax.org.uk> - 2017-02-07 15:42 +0000
        Re: How to compile several C files Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-07 16:19 +0000
          Re: How to compile several C files Richard Heathfield <rjh@cpax.org.uk> - 2017-02-07 16:40 +0000
            Re: How to compile several C files Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-07 17:16 +0000
              Re: How to compile several C files David Brown <david.brown@hesbynett.no> - 2017-02-08 10:19 +0100
          Re: How to compile several C files "James R. Kuyper" <jameskuyper@verizon.net> - 2017-02-07 11:51 -0500
        Re: How to compile several C files Alla _ <modelling.data@gmail.com> - 2017-02-07 08:26 -0800
          Re: How to compile several C files Richard Heathfield <rjh@cpax.org.uk> - 2017-02-07 16:42 +0000
            Re: How to compile several C files Alla _ <modelling.data@gmail.com> - 2017-02-07 10:14 -0800
            Re: How to compile several C files vitale.alla@gmail.com - 2017-02-16 09:49 -0800
        Re: How to compile several C files Ian Collins <ian-news@hotmail.com> - 2017-02-08 17:35 +1300
          Re: How to compile several C files David Brown <david.brown@hesbynett.no> - 2017-02-08 10:28 +0100
            Re: How to compile several C files Ian Collins <ian-news@hotmail.com> - 2017-02-08 22:43 +1300
              Re: How to compile several C files David Brown <david.brown@hesbynett.no> - 2017-02-08 11:29 +0100
        Re: How to compile several C files David Brown <david.brown@hesbynett.no> - 2017-02-08 10:14 +0100
    Re: How to compile several C files James Kuyper <jameskuyper@verizon.net> - 2017-02-07 10:07 -0500
      Re: How to compile several C files Alla _ <modelling.data@gmail.com> - 2017-02-07 07:56 -0800
        Re: How to compile several C files Alla _ <modelling.data@gmail.com> - 2017-02-07 08:24 -0800
          Re: How to compile several C files Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-07 16:44 +0000
            Re: How to compile several C files Alla _ <modelling.data@gmail.com> - 2017-02-07 08:54 -0800
              Re: How to compile several C files "James R. Kuyper" <jameskuyper@verizon.net> - 2017-02-07 12:20 -0500
                Re: How to compile several C files Alla _ <modelling.data@gmail.com> - 2017-02-07 10:05 -0800
                  Re: How to compile several C files Richard Heathfield <rjh@cpax.org.uk> - 2017-02-07 18:27 +0000
                    Re: How to compile several C files Richard Heathfield <rjh@cpax.org.uk> - 2017-02-07 18:40 +0000
                    Re: How to compile several C files Keith Thompson <kst-u@mib.org> - 2017-02-07 12:22 -0800
                    Re: How to compile several C files David Brown <david.brown@hesbynett.no> - 2017-02-08 10:33 +0100
                      Re: How to compile several C files Alla _ <modelling.data@gmail.com> - 2017-02-08 10:25 -0800
        Re: How to compile several C files Keith Thompson <kst-u@mib.org> - 2017-02-07 08:58 -0800
        Re: How to compile several C files "James R. Kuyper" <jameskuyper@verizon.net> - 2017-02-07 12:07 -0500
          Re: How to compile several C files Alla _ <modelling.data@gmail.com> - 2017-02-07 09:14 -0800
            Re: How to compile several C files Richard Heathfield <rjh@cpax.org.uk> - 2017-02-07 17:21 +0000
              Re: How to compile several C files Alla _ <modelling.data@gmail.com> - 2017-02-07 10:14 -0800
              Re: How to compile several C files Alla _ <modelling.data@gmail.com> - 2017-02-07 10:28 -0800
                Re: How to compile several C files Richard Heathfield <rjh@cpax.org.uk> - 2017-02-07 18:43 +0000
                  Re: How to compile several C files Alla _ <modelling.data@gmail.com> - 2017-02-07 10:55 -0800
              Re: How to compile several C files Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-07 19:28 +0000
                Re: How to compile several C files Richard Heathfield <rjh@cpax.org.uk> - 2017-02-07 19:51 +0000
                Re: How to compile several C files David Brown <david.brown@hesbynett.no> - 2017-02-08 11:25 +0100
                  Re: How to compile several C files Richard Heathfield <rjh@cpax.org.uk> - 2017-02-08 12:11 +0000
                    Re: How to compile several C files David Brown <david.brown@hesbynett.no> - 2017-02-08 14:58 +0100
                      Re: How to compile several C files Richard Heathfield <rjh@cpax.org.uk> - 2017-02-08 14:23 +0000
                        Re: How to compile several C files supercat@casperkitty.com - 2017-02-08 07:48 -0800
                          Re: How to compile several C files Richard Heathfield <rjh@cpax.org.uk> - 2017-02-08 16:09 +0000
                            Re: How to compile several C files David Brown <david.brown@hesbynett.no> - 2017-02-08 17:23 +0100
                    Re: How to compile several C files Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-08 15:01 +0000
                      Re: How to compile several C files David Brown <david.brown@hesbynett.no> - 2017-02-08 17:22 +0100
                        Re: How to compile several C files Keith Thompson <kst-u@mib.org> - 2017-02-08 09:27 -0800
                          Re: How to compile several C files supercat@casperkitty.com - 2017-02-08 09:51 -0800
                            Re: How to compile several C files Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-08 21:06 +0000
                              Re: How to compile several C files supercat@casperkitty.com - 2017-02-08 13:20 -0800
                                Re: How to compile several C files Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-08 21:40 +0000
                                  Re: How to compile several C files supercat@casperkitty.com - 2017-02-08 13:49 -0800
                                    Re: How to compile several C files Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-08 23:09 +0000
                                Re: How to compile several C files David Brown <david.brown@hesbynett.no> - 2017-02-08 23:25 +0100
                                  Re: How to compile several C files supercat@casperkitty.com - 2017-02-08 15:17 -0800
                                    Re: How to compile several C files David Brown <david.brown@hesbynett.no> - 2017-02-09 01:17 +0100
                          Re: How to compile several C files David Brown <david.brown@hesbynett.no> - 2017-02-08 23:19 +0100
                            Re: How to compile several C files Keith Thompson <kst-u@mib.org> - 2017-02-08 16:44 -0800
                      Re: How to compile several C files Tim Rentsch <txr@alumni.caltech.edu> - 2017-02-08 22:32 -0800
                    Re: How to compile several C files Robert Wessel <robertwessel2@yahoo.com> - 2017-02-09 04:03 -0600
                    Re: How to compile several C files Ian Collins <ian-news@hotmail.com> - 2017-02-10 07:52 +1300
                  Re: How to compile several C files Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-08 12:12 +0000
                    Re: How to compile several C files BartC <bc@freeuk.com> - 2017-02-08 13:09 +0000
                      Re: How to compile several C files Malcolm McLean <malcolm.mclean5@btinternet.com> - 2017-02-08 05:14 -0800
                      Re: How to compile several C files Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-08 15:32 +0000
                    Re: How to compile several C files David Brown <david.brown@hesbynett.no> - 2017-02-08 15:09 +0100
          Re: How to compile several C files Keith Thompson <kst-u@mib.org> - 2017-02-07 09:22 -0800
            Re: How to compile several C files Gareth Owen <gwowen@gmail.com> - 2017-02-07 18:29 +0000
              Re: How to compile several C files bart4858@gmail.com - 2017-02-07 11:05 -0800
              Re: How to compile several C files Keith Thompson <kst-u@mib.org> - 2017-02-07 12:26 -0800
    Re: How to compile several C files Barry Schwarz <schwarzb@dqel.com> - 2017-02-07 08:34 -0800
      Re: How to compile several C files Alla _ <modelling.data@gmail.com> - 2017-02-07 08:57 -0800
        Re: How to compile several C files "James R. Kuyper" <jameskuyper@verizon.net> - 2017-02-07 12:29 -0500
        Re: How to compile several C files Manfred <noname@invalid.add> - 2017-02-07 19:02 +0100

Page 4 of 4 — ← Prev page 1 2 3 [4]


#103500

Fromsupercat@casperkitty.com
Date2017-02-08 15:17 -0800
Message-ID<bd9fad9b-7c27-4fd8-82d1-3e50d4cf0b4a@googlegroups.com>
In reply to#103496
On Wednesday, February 8, 2017 at 4:25:16 PM UTC-6, David Brown wrote:
> If this was the kind of variable that I'd be likely to pass around using 
> a pointer or address, I would be unlikely to to be doing this macro 
> stuff - I'd just use a const-pointer-to-const in the first place.

Using a const pointer to const would add an extra level of indirection
everywhere the variable is used.  If something is supposed to behave like
a read-only variable, applying the address-of operator to it should yield
a const-qualified pointer to the storage.  The fact that programmers might
want to be able to use memcpy, fwrite, etc. on the variable the same way
as they would any other variable of the same type doesn't mean that the
identifier should behave as a pointer rather than an lvalue.

[toc] | [prev] | [next] | [standalone]


#103503

FromDavid Brown <david.brown@hesbynett.no>
Date2017-02-09 01:17 +0100
Message-ID<o7gcbs$qco$1@dont-email.me>
In reply to#103500
On 09/02/17 00:17, supercat@casperkitty.com wrote:
> On Wednesday, February 8, 2017 at 4:25:16 PM UTC-6, David Brown wrote:
>> If this was the kind of variable that I'd be likely to pass around using
>> a pointer or address, I would be unlikely to to be doing this macro
>> stuff - I'd just use a const-pointer-to-const in the first place.
>
> Using a const pointer to const would add an extra level of indirection
> everywhere the variable is used.  If something is supposed to behave like
> a read-only variable, applying the address-of operator to it should yield
> a const-qualified pointer to the storage.  The fact that programmers might
> want to be able to use memcpy, fwrite, etc. on the variable the same way
> as they would any other variable of the same type doesn't mean that the
> identifier should behave as a pointer rather than an lvalue.
>

/I/ am the programmer when I write my code.  I know that it is very rare 
that I would want to access a read only object sometimes by value, 
sometimes via a pointer.  If it is a big object, the pointer will be 
useful.  If it is a small object, the value is most efficient.  So I 
don't need to go out of my way to be sure that an object can be 
efficiently access both ways.

[toc] | [prev] | [next] | [standalone]


#103495

FromDavid Brown <david.brown@hesbynett.no>
Date2017-02-08 23:19 +0100
Message-ID<o7g5dt$lg$1@dont-email.me>
In reply to#103480
On 08/02/17 18:27, Keith Thompson wrote:
> David Brown <david.brown@hesbynett.no> writes:
> [...]
>> What you can do, and I have done, is something like:
>>
>> 	// In one C file
>> 	int counter_private;
>>
>> 	// In header file
>> 	extern int counter_private;	// Do not use!
>> 	#define counter ((const int) counter_private)
>
> Note that the const in the cast is probably useful as documentation, but
> it's not really necessary, since a cast expression is not an lvalue.
>

Absolutely true.

> You could also have:
>
>     #define counter (+counter_private)
>
> [...]
>

Also true.  I think the cast version makes a little more sense from the 
documentation viewpoint, especially with the "const".  But the "+" 
version avoids a dependency on knowing the exact type (not that that is 
likely to be a problem, even in the face of changes - the "private" 
version is declared right next to the macro version).

[toc] | [prev] | [next] | [standalone]


#103505

FromKeith Thompson <kst-u@mib.org>
Date2017-02-08 16:44 -0800
Message-ID<lnefz8yyz8.fsf@kst-u.example.com>
In reply to#103495
David Brown <david.brown@hesbynett.no> writes:
> On 08/02/17 18:27, Keith Thompson wrote:
>> David Brown <david.brown@hesbynett.no> writes:
>> [...]
>>> What you can do, and I have done, is something like:
>>>
>>> 	// In one C file
>>> 	int counter_private;
>>>
>>> 	// In header file
>>> 	extern int counter_private;	// Do not use!
>>> 	#define counter ((const int) counter_private)
>>
>> Note that the const in the cast is probably useful as documentation, but
>> it's not really necessary, since a cast expression is not an lvalue.
>>
>
> Absolutely true.
>
>> You could also have:
>>
>>     #define counter (+counter_private)
>>
>> [...]
>>
>
> Also true.  I think the cast version makes a little more sense from the 
> documentation viewpoint, especially with the "const".  But the "+" 
> version avoids a dependency on knowing the exact type (not that that is 
> likely to be a problem, even in the face of changes - the "private" 
> version is declared right next to the macro version).

Except that unary "+" can only be applied to arithmetic types -- but the
name "counter" should be a big clue to that anyway.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#103514

FromTim Rentsch <txr@alumni.caltech.edu>
Date2017-02-08 22:32 -0800
Message-ID<kfntw836fj2.fsf@x-alumni2.alumni.caltech.edu>
In reply to#103469
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> Richard Heathfield <rjh@cpax.org.uk> writes:
> <snip>
>> Yes.  Sometimes one has no choice - one arrives on a project to find
>> that they /already/ have a zillion such identifiers, and there isn't
>> the time or the budget to fix the problem (although there always seems
>> to be plenty of time and budget to fix the second-generation problems
>> that ensue!).
>>
>> I /have/ defined a file scope non-const with external linkage in real
>> world code.  Once ever, I think.  It was very, very evil, but for that
>> particular project it was still the lesser of two evils.
>
> It would help to be able to use const data more often but C has a
> problem here:  you can't alter a const object without undefined
> behaviour, and you don't always have the right value at the point of
> definition.  For example, you might want to say
>
>   const char *const program_name;
>
> so that your error reporting module can use it.   But in main() you'd
> have to write
>
>   program_name = argv[0] ? argv[0] : "unknown program";
>
> and, of course, you can't.
>
> You could (and I have done) any of these:
>
> (a) provide a function const char *program_name(void); which will give
>     you a lot of flexibility in the future but can seem a little over
>     the top for simple programs.
>
> (b) static const char *local_program_name;
>     const char *const *const program_name = &local_program_name;
>
>     and use *program_name outside of the main translation unit.
>
> (c) break the type rules.
>
> (d) just allow extern const *program_name;
>
> What do you (generic you -- all of you) like to do in these situations?
> (This example is many not a good one -- please suggest others where
> you've wanted to share unchanging data between TUs.)

My first line of defense in such cases is something like (b),

  .h file
    extern const Type *const static_foo_address;
    #define foo (*static_foo_address)

  .c file
    static Type static_foo;
    const Type *const static_foo_address = &static_foo;

perhaps with some variation in naming choices.

Outside the .c file that defines 'static_foo', use 'foo'.

Inside the .c file that defines 'static_foo', use 'foo' for
read access, and 'static_foo' for write access.

If this approach proves inappropriate for some reason, I'm open
to other ideas.  I don't remember though ever feeling like an
alternative was needed.

[toc] | [prev] | [next] | [standalone]


#103516

FromRobert Wessel <robertwessel2@yahoo.com>
Date2017-02-09 04:03 -0600
Message-ID<l2fo9ch6om5g6u23dcbtsvqcd0u9es2sk6@4ax.com>
In reply to#103452
On Wed, 8 Feb 2017 12:11:23 +0000, Richard Heathfield
<rjh@cpax.org.uk> wrote:

>I always wondered about static data in C++ classes. The whole point of a 
>class is that each object knows all it needs to know about *itself*. A 
>static object in a C++ class has just one value that is shared across 
>all objects of that class.


Well, there are times...

One place I've used them is in code that manages callbacks from the
OS.  Usually you end up in a common routine called by the OS, and that
routine needs to look through a list that maps which actual objects
the callback should get dispatched too.  The static routine needs to
find that list (and it's not called with anything that actually points
to anything like an object instance), so having some reference to that
a static member of the class makes sense.

Alternatively if all the references to that global item were in
methods implemented in a single (non-header) source file, you could
just make the reference an ordinary file-scope static item.  OTOH,
that makes it tough to implement the callback manager as a template
that can create independent callback managers.

[toc] | [prev] | [next] | [standalone]


#103551

FromIan Collins <ian-news@hotmail.com>
Date2017-02-10 07:52 +1300
Message-ID<eg3s3cF1hapU3@mid.individual.net>
In reply to#103452
On 02/ 9/17 01:11 AM, Richard Heathfield wrote:
>
> I always wondered about static data in C++ classes. The whole point of a
> class is that each object knows all it needs to know about *itself*. A
> static object in a C++ class has just one value that is shared across
> all objects of that class.
>
> A friend of mine, who was a student at the time, once tried to explain
> to me why it was a good idea. "Imagine a 'Student' class," he said. (I
> suspect it was a familiar example to him at the time!) He explained that
> it would be very useful for there to be a static member called, say,
> NumStudents, which would record how many students there actually are, so
> that every Student object would always know how many Student objects exist.
>
> "You're a student, right?"
>
> He acknowledged the fact.
>
> "Exactly how many students are there at your university?"
>
> "How should I know? Oh, I see."

Something all of the students share is a better analogy, such as the bar 
of soap.

-- 
Ian

[toc] | [prev] | [next] | [standalone]


#103453

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2017-02-08 12:12 +0000
Message-ID<87o9ycanl0.fsf@bsb.me.uk>
In reply to#103440
David Brown <david.brown@hesbynett.no> writes:

> On 07/02/17 20:28, Ben Bacarisse wrote:
>> Richard Heathfield <rjh@cpax.org.uk> writes:
>> <snip>
>> 
>>> RULE ONE: DO NOT USE FILE SCOPE OBJECTS!
>> 
>> I think it would be better to unravel these intertwined concepts.
>> Objects don't have scope, they have lifetime.  It's names that have
>> scope (and sometimes linkage).  What most people call "globals" are
>> names of objects defined at file scope.  This gives the objects static
>> storage duration (even if not declared static) and gives the names (if
>> not declared static) external linkage.
>
> There is a big distinction between objects defined at file scope with
> "static", and those defined at file scope /without/ "static".  The
> lifetime is the same, the scope of the identifier is the same, but the
> linkage is different.

Yes, I made that distinction but deliberately played it down because I
think it sets the same trap for beginners.

> File static data can often be extremely useful.  It lets you have
> controlled access to the data from a known set of functions (those in
> the same file), without having lots of pointers passed around as
> function parameters.

And that's the problem -- it's easier.  Obviously the situation is more
chaotic if the names have external linkage because they can be accessed
from other translation units, but often the damage has been done simply
by that fact that a bunch of functions now communicate via shared names
rather than parameters and/or return values.

It's all too easy to downplay the role of experience in programming.  I
am sure that when you do this you have considered the alternatives and
the future direction the project might take.  (Will there be threading
one day?  Will you ever want multiple instantiations of this
"module"?...)  The trouble comes when it's simply seen as the obvious
way for two functions to operate on some data.

This is why rules are so hard to come by in programming.  C has no
modules in any modern sense, but it does have translation units with
"internal" names and sometimes that's the best way to write a part of a
program.  But much more often students will put data outside of a
function just because its so much simpler.  Writing a stack?  Define an
array at file scope (make it static to keep the teacher happy) and you
have simple push and pop function.  But you now have a stack you can
only have one of.

> It is somewhat like having a singleton class in
> C++, with the static data being the data members, static functions being
> private methods, and non-static functions being public methods.

Sure.  Knowing when that's the right design does take some time to
develop.  Mind you, it could be argued that knowing how to convert
between one for and another is a useful C skill.  Taking all your static
file-scope data and putting unto a struct that gets passed about is
something I'm sure we've all done more than once!

> "globals" usually (IME) refers to file scope data that is /not/ static,
> and thus has external linkage and can be access from other files.  That
> is when you need to be very wary - any other files can access the data
> so you have lost that control.  Global data like this is often viewed as
> "evil", and that's not a bad first approximation.  It can be useful when
> used correctly - but you need to be very careful.

The trouble is that for small programs the distinction is simply
technical.  A one-file program has the same good or bad design if the
file-scope names have internal or external linkage.

> Global constant data is much less of a problem, but like non-static
> functions the identifiers use a program-wide namespace.  Defining a
> non-static const array with the name "data" is a bad idea - though it
> might be okay for static const data.

Yes, there's a whole sliding scale of problems from multiple translation
units modifying shared globals all over the place, to a few bits of
constant of data shared between TUs, with the latter being seen by many
as "no problem at all" provided the names are not an issue.

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#103456

FromBartC <bc@freeuk.com>
Date2017-02-08 13:09 +0000
Message-ID<o7f562$24a$1@dont-email.me>
In reply to#103453
On 08/02/2017 12:12, Ben Bacarisse wrote:
> David Brown <david.brown@hesbynett.no> writes:

>> File static data can often be extremely useful.  It lets you have
>> controlled access to the data from a known set of functions (those in
>> the same file), without having lots of pointers passed around as
>> function parameters.

> It's all too easy to downplay the role of experience in programming.  I
> am sure that when you do this you have considered the alternatives and
> the future direction the project might take.  (Will there be threading
> one day?  Will you ever want multiple instantiations of this
> "module"?...)  The trouble comes when it's simply seen as the obvious
> way for two functions to operate on some data.

Suppose a program uses static file-scope data, the sort that you suggest 
is a bad way of sharing data across functions.

Suppose also that C has nested functions (this is a gcc extension actually).

Now you can choose to wrap one function around the entire program. Those 
file-scope variables now become local variables.

Does this eliminate the problems with how those variables are shared 
across the nested functions, or not?

After all, when you have declarations in nested block scopes, code in 
different inner scopes can share data declared in a common outer scope; 
I'm struggling to see the difference from sharing file-scope data.

-- 
Bartc

[toc] | [prev] | [next] | [standalone]


#103457

FromMalcolm McLean <malcolm.mclean5@btinternet.com>
Date2017-02-08 05:14 -0800
Message-ID<ac2ff6da-27c8-43fb-89df-506dcc7ac3c7@googlegroups.com>
In reply to#103456
On Wednesday, February 8, 2017 at 1:09:09 PM UTC, Bart wrote:
> On 08/02/2017 12:12, Ben Bacarisse wrote:
> > David Brown <david.brown@hesbynett.no> writes:
> 
> >> File static data can often be extremely useful.  It lets you have
> >> controlled access to the data from a known set of functions (those in
> >> the same file), without having lots of pointers passed around as
> >> function parameters.
> 
> > It's all too easy to downplay the role of experience in programming.  I
> > am sure that when you do this you have considered the alternatives and
> > the future direction the project might take.  (Will there be threading
> > one day?  Will you ever want multiple instantiations of this
> > "module"?...)  The trouble comes when it's simply seen as the obvious
> > way for two functions to operate on some data.
> 
> Suppose a program uses static file-scope data, the sort that you suggest 
> is a bad way of sharing data across functions.
> 
> Suppose also that C has nested functions (this is a gcc extension actually).
> 
> Now you can choose to wrap one function around the entire program. Those 
> file-scope variables now become local variables.
> 
> Does this eliminate the problems with how those variables are shared 
> across the nested functions, or not?
> 
> After all, when you have declarations in nested block scopes, code in 
> different inner scopes can share data declared in a common outer scope; 
> I'm struggling to see the difference from sharing file-scope data.
> 
It's quite common in a video game for a parameter to be "the world". Just as a real
object like an apple needs to know everything about it's environment if it is to calculate
its own path from tree to ground, that's also often true of virtual objects.

[toc] | [prev] | [next] | [standalone]


#103471

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2017-02-08 15:32 +0000
Message-ID<877f50aebc.fsf@bsb.me.uk>
In reply to#103456
BartC <bc@freeuk.com> writes:

> On 08/02/2017 12:12, Ben Bacarisse wrote:
>> David Brown <david.brown@hesbynett.no> writes:
>
>>> File static data can often be extremely useful.  It lets you have
>>> controlled access to the data from a known set of functions (those in
>>> the same file), without having lots of pointers passed around as
>>> function parameters.
>
>> It's all too easy to downplay the role of experience in programming.  I
>> am sure that when you do this you have considered the alternatives and
>> the future direction the project might take.  (Will there be threading
>> one day?  Will you ever want multiple instantiations of this
>> "module"?...)  The trouble comes when it's simply seen as the obvious
>> way for two functions to operate on some data.
>
> Suppose a program uses static file-scope data, the sort that you
> suggest is a bad way of sharing data across functions.
>
> Suppose also that C has nested functions (this is a gcc extension actually).
>
> Now you can choose to wrap one function around the entire
> program. Those file-scope variables now become local variables.
>
> Does this eliminate the problems with how those variables are shared
> across the nested functions, or not?

Yes, usually.  The nested functions are now no longer independent being
local to some larger operation so they can be understood in this more
limited context.

> After all, when you have declarations in nested block scopes, code in
> different inner scopes can share data declared in a common outer
> scope; I'm struggling to see the difference from sharing file-scope
> data.

The problem is not the sharing per-se but the program structure.  If you
can do what you say -- wrap the whole lot up in another function it says
something about the structure.

To keep it concrete, if the old code was a stack with a file-scope array
and push and pop functions, the fact that you can wrap it up in a larger
function make it quite clear that the stack is use din only one place --
this larger function.  That makes answering questions like, is it OK
that there can be only one stack, much simpler to answer.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#103466

FromDavid Brown <david.brown@hesbynett.no>
Date2017-02-08 15:09 +0100
Message-ID<o7f8oa$etb$1@dont-email.me>
In reply to#103453
On 08/02/17 13:12, Ben Bacarisse wrote:
> David Brown <david.brown@hesbynett.no> writes:
> 
>> On 07/02/17 20:28, Ben Bacarisse wrote:
>>> Richard Heathfield <rjh@cpax.org.uk> writes:
>>> <snip>
>>>
>>>> RULE ONE: DO NOT USE FILE SCOPE OBJECTS!
>>>
>>> I think it would be better to unravel these intertwined concepts.
>>> Objects don't have scope, they have lifetime.  It's names that have
>>> scope (and sometimes linkage).  What most people call "globals" are
>>> names of objects defined at file scope.  This gives the objects static
>>> storage duration (even if not declared static) and gives the names (if
>>> not declared static) external linkage.
>>
>> There is a big distinction between objects defined at file scope with
>> "static", and those defined at file scope /without/ "static".  The
>> lifetime is the same, the scope of the identifier is the same, but the
>> linkage is different.
> 
> Yes, I made that distinction but deliberately played it down because I
> think it sets the same trap for beginners.
> 
>> File static data can often be extremely useful.  It lets you have
>> controlled access to the data from a known set of functions (those in
>> the same file), without having lots of pointers passed around as
>> function parameters.
> 
> And that's the problem -- it's easier.  Obviously the situation is more
> chaotic if the names have external linkage because they can be accessed
> from other translation units, but often the damage has been done simply
> by that fact that a bunch of functions now communicate via shared names
> rather than parameters and/or return values.
> 
> It's all too easy to downplay the role of experience in programming.  I
> am sure that when you do this you have considered the alternatives and
> the future direction the project might take.  (Will there be threading
> one day?  Will you ever want multiple instantiations of this
> "module"?...)  The trouble comes when it's simply seen as the obvious
> way for two functions to operate on some data.
> 

I can accept that.  In my code, I generally have a very clear idea of
what future directions will bring, and I often have an emphasis on
efficiency (run-time speed and/or code size) rather than flexibility for
the future.

> This is why rules are so hard to come by in programming.  

Yes.  For any question of the form "what's the best way to do this?", or
"is this a good idea?", the answer is invariably "it depends".

> C has no
> modules in any modern sense, but it does have translation units with
> "internal" names and sometimes that's the best way to write a part of a
> program.  But much more often students will put data outside of a
> function just because its so much simpler.  Writing a stack?  Define an
> array at file scope (make it static to keep the teacher happy) and you
> have simple push and pop function.  But you now have a stack you can
> only have one of.

And that is absolutely /fine/ if one stack is all your program needs.
Too much generalisation can be bad too.  If I am writing a program to
control a car engine, I can make the assumption that there is only one
car and one engine, and I don't need to clutter my code with pointers to
engines in and out of every function.  If the day comes that I need to
support a two-engined car, so much is different that it is a new program
- and the refactoring can be done at that time.

I fully appreciate that students should get used to general ideas and
not "shortcuts".  But sometimes it makes sense to solve today's problems
rather than trying to solve all the potential problems of the future.

> 
>> It is somewhat like having a singleton class in
>> C++, with the static data being the data members, static functions being
>> private methods, and non-static functions being public methods.
> 
> Sure.  Knowing when that's the right design does take some time to
> develop.  Mind you, it could be argued that knowing how to convert
> between one for and another is a useful C skill.  Taking all your static
> file-scope data and putting unto a struct that gets passed about is
> something I'm sure we've all done more than once!

Yes, been there and done that.

> 
>> "globals" usually (IME) refers to file scope data that is /not/ static,
>> and thus has external linkage and can be access from other files.  That
>> is when you need to be very wary - any other files can access the data
>> so you have lost that control.  Global data like this is often viewed as
>> "evil", and that's not a bad first approximation.  It can be useful when
>> used correctly - but you need to be very careful.
> 
> The trouble is that for small programs the distinction is simply
> technical.  A one-file program has the same good or bad design if the
> file-scope names have internal or external linkage.

I think even when working on small one-file programs, students should
get in the habit of putting "static" in front of all file-scope data and
all functions, unless they have very good reason not to - and for
single-file programs, that basically means only "main" does not have
"static".

> 
>> Global constant data is much less of a problem, but like non-static
>> functions the identifiers use a program-wide namespace.  Defining a
>> non-static const array with the name "data" is a bad idea - though it
>> might be okay for static const data.
> 
> Yes, there's a whole sliding scale of problems from multiple translation
> units modifying shared globals all over the place, to a few bits of
> constant of data shared between TUs, with the latter being seen by many
> as "no problem at all" provided the names are not an issue.
> 
> <snip>
> 

[toc] | [prev] | [next] | [standalone]


#103392

FromKeith Thompson <kst-u@mib.org>
Date2017-02-07 09:22 -0800
Message-ID<lno9yd29wk.fsf@kst-u.example.com>
In reply to#103386
"James R. Kuyper" <jameskuyper@verizon.net> writes:
[...]
> All of the following are object definitions. They do NOT belong in a 
> header file - you need to move each of these definitions to one or the 
> other of the *.c files. If an object's name is used in both *.c file, 
> you should have a declaration for that object in one of the two header 
> files. But that declaration would look different from from these 
> definitions. At a minimum, you would put "extern" at the beginning of 
> each declaration. Also, for the arrays, it's not necessary to put the 
> actual number of elements in the object declaration, only in the object 
> definition.

It's not necessary to include the length in the declaration.  For example
you could have
    extern balance bal[];
in a .h file and
    balance bal[YEARS];
in the corresponding .c file.

But *if* it makes sense to declare an array object in a header, then
it's not necessarily a bad idea to include the bounds in the
declaration.  It lets you use `sizeof bal / sizeof bal[0]` to compute
the number of elements, for example.

On the other hand, it's likely better not to make the array object's
name globally visible in the first place.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#103406

FromGareth Owen <gwowen@gmail.com>
Date2017-02-07 18:29 +0000
Message-ID<874m05kg6o.fsf@gmail.com>
In reply to#103392
Keith Thompson <kst-u@mib.org> writes:

> "James R. Kuyper" <jameskuyper@verizon.net> writes:
> [...]
>> All of the following are object definitions. They do NOT belong in a 
>> header file - you need to move each of these definitions to one or the 
>> other of the *.c files. If an object's name is used in both *.c file, 
>> you should have a declaration for that object in one of the two header 
>> files. But that declaration would look different from from these 
>> definitions. At a minimum, you would put "extern" at the beginning of 
>> each declaration. Also, for the arrays, it's not necessary to put the 
>> actual number of elements in the object declaration, only in the object 
>> definition.
>
> It's not necessary to include the length in the declaration.  For example
> you could have
>     extern balance bal[];
> in a .h file and
>     balance bal[YEARS];
> in the corresponding .c file.

As an interesting exercise for Bart and Malcolm,
I recommend that they put

extern balance *bal;

in the .h file and

balance bal[YEARS];

in the .c file, and rely on the the equivalence of arrays and pointers.

[toc] | [prev] | [next] | [standalone]


#103410

Frombart4858@gmail.com
Date2017-02-07 11:05 -0800
Message-ID<cf5e149e-4028-47da-99ff-f4b2cbca222e@googlegroups.com>
In reply to#103406
On Tuesday, 7 February 2017 18:29:46 UTC, gwowen  wrote:
> Keith Thompson <kst-u@mib.org> writes:
> 
> > "James R. Kuyper" <jameskuyper@verizon.net> writes:
> > [...]
> >> All of the following are object definitions. They do NOT belong in a 
> >> header file - you need to move each of these definitions to one or the 
> >> other of the *.c files. If an object's name is used in both *.c file, 
> >> you should have a declaration for that object in one of the two header 
> >> files. But that declaration would look different from from these 
> >> definitions. At a minimum, you would put "extern" at the beginning of 
> >> each declaration. Also, for the arrays, it's not necessary to put the 
> >> actual number of elements in the object declaration, only in the object 
> >> definition.
> >
> > It's not necessary to include the length in the declaration.  For example
> > you could have
> >     extern balance bal[];
> > in a .h file and
> >     balance bal[YEARS];
> > in the corresponding .c file.
> 
> As an interesting exercise for Bart and Malcolm,
> I recommend that they put
> 
> extern balance *bal;
> 
> in the .h file and
> 
> balance bal[YEARS];
> 
> in the .c file, and rely on the the equivalence of arrays and pointers.

The equivalence comes into play inside expressions when either of those can be accessed as:

  bal[i]

But those two declarations won't compile I think if both are visible at the same time. If not, then things can go wrong as bal[i] in one module will generate code based on bal being a value array of balance, and the other a pointer to balance which also needs setup code.

(In languages where only one declaration of bal exists even when it is shared across modules, this mixup can't happen.)

[toc] | [prev] | [next] | [standalone]


#103418

FromKeith Thompson <kst-u@mib.org>
Date2017-02-07 12:26 -0800
Message-ID<ln7f5121er.fsf@kst-u.example.com>
In reply to#103406
Gareth Owen <gwowen@gmail.com> writes:
> Keith Thompson <kst-u@mib.org> writes:
>> "James R. Kuyper" <jameskuyper@verizon.net> writes:
>> [...]
>>> All of the following are object definitions. They do NOT belong in a 
>>> header file - you need to move each of these definitions to one or the 
>>> other of the *.c files. If an object's name is used in both *.c file, 
>>> you should have a declaration for that object in one of the two header 
>>> files. But that declaration would look different from from these 
>>> definitions. At a minimum, you would put "extern" at the beginning of 
>>> each declaration. Also, for the arrays, it's not necessary to put the 
>>> actual number of elements in the object declaration, only in the object 
>>> definition.
>>
>> It's not necessary to include the length in the declaration.  For example
>> you could have
>>     extern balance bal[];
>> in a .h file and
>>     balance bal[YEARS];
>> in the corresponding .c file.
>
> As an interesting exercise for Bart and Malcolm,
> I recommend that they put
>
> extern balance *bal;
>
> in the .h file and
>
> balance bal[YEARS];
>
> in the .c file, and rely on the the equivalence of arrays and pointers.

I guess you're joking.  If you are, somebody other than Bart or Malcolm
might take you seriously, so I'm going to spoil the joke.

Don't do this.  Arrays and pointers are not equivalent.  The compiler
will catch this if you #include the .h file in the .c file that defines
the array, but if you get past that you'll be lying to the compiler,
telling it that an array object and a pointer object occupy the same
location.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#103376

FromBarry Schwarz <schwarzb@dqel.com>
Date2017-02-07 08:34 -0800
Message-ID<uarj9cp0s0bdna7fu481srcsjnnk1u1ehf@4ax.com>
In reply to#103352
On Tue, 7 Feb 2017 06:10:37 -0800 (PST), Alla _
<modelling.data@gmail.com> wrote:

>Hello!
>
>I have a program, which I would like to separate into two C files,
>and two .h files. The non-separated version works, but it would
>be logically correct to separate it into two parts.
>Actually, I already have done so. When I tried to
>compile two parts, I got a cryptic message saying that there were 

Surely you know by now that this tells us nothing.

>some duplicates. Before digging deeper into that error message,
>I would like to found out if I correctly compile both files, and what 
>are the rules. 

If you received compiler error diagnostics, then you compiled.  If
they were from the linker, who knows.

One frequent cause of duplication is defining an object in a header.
When that happens, every .c file that includes the header will define
the object at file scope and the linker will detect the multiple
copies.  Header files should contain declarations (including the
external declarations for "global" objects which you should try to
avoid having at all), prototypes, structure and union type
definitions, typedef definitions, and macro definitions.

If you have any global objects, they should be defined in exactly one
.c file.  My preference is the one that contains main.

If you have any objects defined at file scope for use within that file
only, add the static keyword to the definition.  If for some reason
you have duplicate function names in different .c files, define them
as static also.

-- 
Remove del for email

[toc] | [prev] | [next] | [standalone]


#103384

FromAlla _ <modelling.data@gmail.com>
Date2017-02-07 08:57 -0800
Message-ID<7cb26f6d-c29c-43d4-b383-5d0b5a5793bd@googlegroups.com>
In reply to#103376
On Tuesday, February 7, 2017 at 7:34:29 PM UTC+3, Barry Schwarz wrote:
> On Tue, 7 Feb 2017 06:10:37 -0800 (PST), Alla _
> <modelling.data@gmail.com> wrote:
> 
> >Hello!
> >
> >I have a program, which I would like to separate into two C files,
> >and two .h files. The non-separated version works, but it would
> >be logically correct to separate it into two parts.
> >Actually, I already have done so. When I tried to
> >compile two parts, I got a cryptic message saying that there were 
> 
> Surely you know by now that this tells us nothing.
> 
> >some duplicates. Before digging deeper into that error message,
> >I would like to found out if I correctly compile both files, and what 
> >are the rules. 
> 
> If you received compiler error diagnostics, then you compiled.  If
> they were from the linker, who knows.
> 
> One frequent cause of duplication is defining an object in a header.
> When that happens, every .c file that includes the header will define
> the object at file scope and the linker will detect the multiple
> copies.  Header files should contain declarations (including the
> external declarations for "global" objects which you should try to
> avoid having at all), prototypes, structure and union type
> definitions, typedef definitions, and macro definitions.
> 
> If you have any global objects, they should be defined in exactly one
> .c file.  My preference is the one that contains main.
I see. It means that putting them into a header file was a 
bad idea, correct? But if I have them only in one .c file,
how will the second .c see them and use them? I thought
that putting them into a header allows access to those global
objects by any .c that includes the header. 
> 
> If you have any objects defined at file scope for use within that file
> only, add the static keyword to the definition.  If for some reason
> you have duplicate function names in different .c files, define them
> as static also.
> 
> -- 
> Remove del for email

[toc] | [prev] | [next] | [standalone]


#103393

From"James R. Kuyper" <jameskuyper@verizon.net>
Date2017-02-07 12:29 -0500
Message-ID<09cfc181-96dc-ba6f-b03a-37b7b3b351d2@verizon.net>
In reply to#103384
On 02/07/2017 11:57 AM, Alla _ wrote:
> On Tuesday, February 7, 2017 at 7:34:29 PM UTC+3, Barry Schwarz wrote:
...
>> If you have any global objects, they should be defined in exactly one
>> .c file.  My preference is the one that contains main.
> I see. It means that putting them into a header file was a
> bad idea, correct? But if I have them only in one .c file,
> how will the second .c see them and use them? I thought

By putting a declaration for that object in the header file.

foo.h:
     extern int baz; // declaration, but NOT definition

foo.c:
     #include "foo.h"
     int baz; // Both declaration and definition
     // Other code that uses baz

bar.c:
     #include "foo.h"
     // Other code that uses baz

Note one key point: the reason why foo.c #includes "foo.h" is not that 
it needs to do so in order to work properly - the definition of baz in 
foo.c takes care of that. The reason for #including "foo.h" is that it 
will trigger a diagnostic message if the declaration for baz gives a 
type that is not compatible with the type used in the definition of baz.

[toc] | [prev] | [next] | [standalone]


#103398

FromManfred <noname@invalid.add>
Date2017-02-07 19:02 +0100
Message-ID<o7d24b$l2q$1@gioia.aioe.org>
In reply to#103384
On 2/7/2017 5:57 PM, Alla _ wrote:
>> If you have any global objects, they should be defined in exactly one
>> .c file.  My preference is the one that contains main.
> I see. It means that putting them into a header file was a
> bad idea, correct? But if I have them only in one .c file,
> how will the second .c see them and use them? I thought
> that putting them into a header allows access to those global
> objects by any .c that includes the header.

Look for what the 'extern' keyword does to variable declarations.
That said, the advice that others have given for alternatives to global 
variables may be preferable.

[toc] | [prev] | [standalone]


Page 4 of 4 — ← Prev page 1 2 3 [4]

Back to top | Article view | comp.lang.c


csiph-web