Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #103352 > unrolled thread
| Started by | Alla _ <modelling.data@gmail.com> |
|---|---|
| First post | 2017-02-07 06:10 -0800 |
| Last post | 2017-02-07 19:02 +0100 |
| Articles | 20 on this page of 80 — 18 participants |
Back to article view | Back to comp.lang.c
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]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-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]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-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]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2017-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]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2017-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-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]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-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]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2017-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-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]
| From | Gareth Owen <gwowen@gmail.com> |
|---|---|
| Date | 2017-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]
| From | bart4858@gmail.com |
|---|---|
| Date | 2017-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-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]
| From | Barry Schwarz <schwarzb@dqel.com> |
|---|---|
| Date | 2017-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]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2017-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]
| From | "James R. Kuyper" <jameskuyper@verizon.net> |
|---|---|
| Date | 2017-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]
| From | Manfred <noname@invalid.add> |
|---|---|
| Date | 2017-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