Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #103611 > unrolled thread
| Started by | BartC <bc@freeuk.com> |
|---|---|
| First post | 2017-02-10 17:16 +0000 |
| Last post | 2017-02-11 03:17 -0800 |
| Articles | 20 on this page of 105 — 19 participants |
Back to article view | Back to comp.lang.c
Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-10 17:16 +0000
Re: Is 'extern' necessary? Keith Thompson <kst-u@mib.org> - 2017-02-10 09:33 -0800
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-10 18:41 +0000
Re: Is 'extern' necessary? Keith Thompson <kst-u@mib.org> - 2017-02-10 12:09 -0800
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-10 20:29 +0000
Re: Is 'extern' necessary? Keith Thompson <kst-u@mib.org> - 2017-02-10 13:26 -0800
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-10 22:56 +0000
Re: Is 'extern' necessary? jameskuyper@verizon.net - 2017-02-10 20:19 -0800
Re: Is 'extern' necessary? "James R. Kuyper" <jameskuyper@verizon.net> - 2017-02-11 09:53 -0500
Re: Is 'extern' necessary? Tim Rentsch <txr@alumni.caltech.edu> - 2017-02-13 05:19 -0800
Re: Is 'extern' necessary? jameskuyper@verizon.net - 2017-02-10 12:09 -0800
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-10 20:50 +0000
Re: Is 'extern' necessary? supercat@casperkitty.com - 2017-02-10 13:09 -0800
Re: Is 'extern' necessary? Keith Thompson <kst-u@mib.org> - 2017-02-10 13:33 -0800
Re: Is 'extern' necessary? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-10 23:23 +0000
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-10 23:35 +0000
Re: Is 'extern' necessary? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-11 00:34 +0000
Re: Is 'extern' necessary? David Brown <david.brown@hesbynett.no> - 2017-02-13 12:41 +0100
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-13 13:14 +0000
Re: Is 'extern' necessary? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-13 14:05 +0000
Re: Is 'extern' necessary? jameskuyper@verizon.net - 2017-02-13 07:49 -0800
Re: Is 'extern' necessary? jameskuyper@verizon.net - 2017-02-10 19:33 -0800
Re: Is 'extern' necessary? supercat@casperkitty.com - 2017-02-11 09:41 -0800
Re: Is 'extern' necessary? Keith Thompson <kst-u@mib.org> - 2017-02-11 10:19 -0800
Re: Is 'extern' necessary? "James R. Kuyper" <jameskuyper@verizon.net> - 2017-02-11 13:39 -0500
Re: Is 'extern' necessary? supercat@casperkitty.com - 2017-02-12 10:10 -0800
Re: Is 'extern' necessary? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2017-02-10 14:59 -0800
Re: Is 'extern' necessary? David Brown <david.brown@hesbynett.no> - 2017-02-13 12:33 +0100
Re: Is 'extern' necessary? Siri Cruise <chine.bleu@yahoo.com> - 2017-02-10 09:35 -0800
Re: Is 'extern' necessary? Keith Thompson <kst-u@mib.org> - 2017-02-10 12:12 -0800
Re: Is 'extern' necessary? jameskuyper@verizon.net - 2017-02-10 10:38 -0800
Re: Is 'extern' necessary? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-10 21:10 +0000
Re: Is 'extern' necessary? supercat@casperkitty.com - 2017-02-10 13:25 -0800
Re: Is 'extern' necessary? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2017-02-10 14:53 -0800
Re: Is 'extern' necessary? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2017-02-10 15:06 -0800
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-10 23:24 +0000
Re: Is 'extern' necessary? Ian Collins <ian-news@hotmail.com> - 2017-02-11 12:34 +1300
Re: Is 'extern' necessary? David Brown <david.brown@hesbynett.no> - 2017-02-13 13:14 +0100
Re: Is 'extern' necessary? GOTHIER Nathan <nathan.gothier@gmail.com> - 2017-02-13 13:44 +0100
Re: Is 'extern' necessary? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-13 14:13 +0000
Re: Is 'extern' necessary? David Brown <david.brown@hesbynett.no> - 2017-02-13 15:16 +0100
Re: Is 'extern' necessary? GOTHIER Nathan <nathan.gothier@gmail.com> - 2017-02-13 17:24 +0100
Re: Is 'extern' necessary? "James R. Kuyper" <jameskuyper@verizon.net> - 2017-02-13 14:24 -0500
Re: Is 'extern' necessary? David Brown <david.brown@hesbynett.no> - 2017-02-13 23:29 +0100
Re: Is 'extern' necessary? Keith Thompson <kst-u@mib.org> - 2017-02-13 11:06 -0800
Re: Is 'extern' necessary? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2017-02-13 11:15 -0800
Re: Is 'extern' necessary? "James R. Kuyper" <jameskuyper@verizon.net> - 2017-02-13 11:48 -0500
Re: Is 'extern' necessary? supercat@casperkitty.com - 2017-02-13 09:03 -0800
Re: Is 'extern' necessary? David Brown <david.brown@hesbynett.no> - 2017-02-13 23:37 +0100
Re: Is 'extern' necessary? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2017-02-10 15:40 -0800
Re: Is 'extern' necessary? Tim Rentsch <txr@alumni.caltech.edu> - 2017-02-13 05:09 -0800
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-13 13:46 +0000
Re: Is 'extern' necessary? Keith Thompson <kst-u@mib.org> - 2017-02-13 09:52 -0800
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-13 19:19 +0000
Re: Is 'extern' necessary? Keith Thompson <kst-u@mib.org> - 2017-02-13 11:34 -0800
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-13 20:13 +0000
Re: Is 'extern' necessary? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2017-02-13 13:11 -0800
Re: Is 'extern' necessary? David Brown <david.brown@hesbynett.no> - 2017-02-14 00:33 +0100
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-14 01:02 +0000
Re: Is 'extern' necessary? David Brown <david.brown@hesbynett.no> - 2017-02-14 09:28 +0100
Re: Is 'extern' necessary? Robert Wessel <robertwessel2@yahoo.com> - 2017-02-14 03:31 -0600
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-14 11:42 +0000
Re: Is 'extern' necessary? David Brown <david.brown@hesbynett.no> - 2017-02-14 13:29 +0100
Re: Is 'extern' necessary? supercat@casperkitty.com - 2017-02-14 05:16 -0800
Re: Is 'extern' necessary? David Brown <david.brown@hesbynett.no> - 2017-02-14 14:51 +0100
Re: Is 'extern' necessary? supercat@casperkitty.com - 2017-02-14 07:24 -0800
Re: Is 'extern' necessary? David Brown <david.brown@hesbynett.no> - 2017-02-14 21:35 +0100
Re: Is 'extern' necessary? James Kuyper <jameskuyper@verizon.net> - 2017-02-14 15:53 -0500
Re: Is 'extern' necessary? David Brown <david.brown@hesbynett.no> - 2017-02-15 09:31 +0100
Re: Is 'extern' necessary? "James R. Kuyper" <jameskuyper@verizon.net> - 2017-02-15 11:36 -0500
Re: Is 'extern' necessary? Keith Thompson <kst-u@mib.org> - 2017-02-15 09:12 -0800
Re: Is 'extern' necessary? "James R. Kuyper" <jameskuyper@verizon.net> - 2017-02-15 12:58 -0500
Re: Is 'extern' necessary? supercat@casperkitty.com - 2017-02-15 10:01 -0800
Re: Is 'extern' necessary? jameskuyper@verizon.net - 2017-02-15 10:55 -0800
Re: Is 'extern' necessary? supercat@casperkitty.com - 2017-02-15 11:42 -0800
Re: Is 'extern' necessary? jameskuyper@verizon.net - 2017-02-15 12:28 -0800
Re: Is 'extern' necessary? supercat@casperkitty.com - 2017-02-15 13:58 -0800
Re: Is 'extern' necessary? Keith Thompson <kst-u@mib.org> - 2017-02-14 08:54 -0800
Re: Is 'extern' necessary? Keith Thompson <kst-u@mib.org> - 2017-02-14 08:51 -0800
Re: Is 'extern' necessary? Richard Heathfield <rjh@cpax.org.uk> - 2017-02-14 17:32 +0000
Re: Is 'extern' necessary? Gareth Owen <gwowen@gmail.com> - 2017-02-14 17:45 +0000
Re: Is 'extern' necessary? David Brown <david.brown@hesbynett.no> - 2017-02-14 21:38 +0100
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-14 23:26 +0000
Re: Is 'extern' necessary? Keith Thompson <kst-u@mib.org> - 2017-02-14 16:33 -0800
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-15 00:47 +0000
Re: Is 'extern' necessary? Jean-Marc Bourguet <jm@bourguet.org> - 2017-02-14 18:17 +0100
Re: Is 'extern' necessary? Keith Thompson <kst-u@mib.org> - 2017-02-14 09:47 -0800
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-14 18:36 +0000
Re: Is 'extern' necessary? jameskuyper@verizon.net - 2017-02-14 11:20 -0800
Re: Is 'extern' necessary? supercat@casperkitty.com - 2017-02-14 11:42 -0800
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-14 20:22 +0000
Re: Is 'extern' necessary? Robert Wessel <robertwessel2@yahoo.com> - 2017-02-14 17:58 -0600
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-15 01:29 +0000
Re: Is 'extern' necessary? Robert Wessel <robertwessel2@yahoo.com> - 2017-02-16 05:02 -0600
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-16 11:38 +0000
Re: Is 'extern' necessary? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-16 14:37 +0000
Re: Is 'extern' necessary? BartC <bc@freeuk.com> - 2017-02-16 15:43 +0000
Re: Is 'extern' necessary? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-16 16:08 +0000
Re: Is 'extern' necessary? GOTHIER Nathan <nathan.gothier@gmail.com> - 2017-02-16 18:42 +0100
Re: Is 'extern' necessary? David Brown <david.brown@hesbynett.no> - 2017-02-15 09:47 +0100
Re: Is 'extern' necessary? Robert Wessel <robertwessel2@yahoo.com> - 2017-02-16 05:05 -0600
Re: Is 'extern' necessary? Tim Rentsch <txr@alumni.caltech.edu> - 2017-02-15 16:53 -0800
Re: Is 'extern' necessary? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-10 23:55 +0000
Re: Is 'extern' necessary? Les Cargill <lcargill99@comcast.com> - 2017-02-10 19:24 -0600
Re: Is 'extern' necessary? void <nathan.gothier@gmail.com> - 2017-02-11 03:17 -0800
Page 3 of 6 — ← Prev page 1 2 [3] 4 5 6 Next page →
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-02-13 15:16 +0100 |
| Message-ID | <o7sevq$l13$1@dont-email.me> |
| In reply to | #103790 |
On 13/02/17 13:44, GOTHIER Nathan wrote: > On Mon, 13 Feb 2017 13:14:34 +0100 > David Brown <david.brown@hesbynett.no> wrote: > >> One good reason why you might not see "extern" so often in code is that >> it is only needed when data is shared directly amongst translation >> units, and that is usually considered a bad (or at least risky) >> practice. And one bad reason is that you (Bart) are not alone in >> misunderstanding how C linking and definitions work, and in thinking "it >> seems to work if I do this - it must be the correct way to write the code". > > I agree the linkage definition is rather obscure in the C standard. > It is something that you need to read about and think about to understand. If you don't like reading the C standards (which are references, not tutorials), then there are plenty of books and online resources that will explain it well enough. > >> Yes. Typically you have the "extern" declarations in the header files, >> and you have the definitions (without "extern" or "static") in the >> source files. Any definition that does not have a matching "extern" >> declaration in an appropriate header, should be marked "static". > > If you put a non "extern" object with "static", its lifetime is longer than > necessary and you prevent the compiler to free unused memory space for example > when leaving a block. We are talking about file-scope objects here - they have program lifetime. No one (who understands C) would make a local variable "static" without good reason, because that is a different case altogether. > The linkage defines links between objects like pointers. > It is useful to distinguish objects named with the same identifier. Linkage determines whether names are tied together. All identifiers with the same name and external linkage are "joined" at link time. You can pretend that identifiers with internal linkage have their scope attached to their symbol identifier. (And identifiers with no linkage never escape anyway.) > > >> Personally, I also put "extern" in my function declarations in headers. >> It is not required (since the lack of a function body already marks it >> as a non-defining declaration), and many people don't use it, but I feel >> it gives a clearer indication that this is a "global" function. > > Prototypes should always be declared as "extern" since it points to a previous > definition. > No. Prototypes are usually in advance of the definition, not /after/ the definition (assuming the definition is in the same TU as the prototype in question). And if you have a "static" function definition, it is perfectly reasonable to have a "static" prototype for it in advance of the function definition - you do that if you have mutually recursive static functions, or if you just prefer a different order for defining your functions.
[toc] | [prev] | [next] | [standalone]
| From | GOTHIER Nathan <nathan.gothier@gmail.com> |
|---|---|
| Date | 2017-02-13 17:24 +0100 |
| Message-ID | <20170213172401.3de343e6dcce4212fa1334e8@gmail.com> |
| In reply to | #103803 |
On Mon, 13 Feb 2017 15:16:07 +0100 David Brown <david.brown@hesbynett.no> wrote: > No. Prototypes are usually in advance of the definition, not /after/ > the definition (assuming the definition is in the same TU as the > prototype in question). And if you have a "static" function definition, > it is perfectly reasonable to have a "static" prototype for it in > advance of the function definition - you do that if you have mutually > recursive static functions, or if you just prefer a different order for > defining your functions. I'm amazed how you make things right using corner cases... Your quest for the only one truth show your devotion as a good Christian. :-) Usually prototypes are used to access definitions provided to the linker as a library. Sometimes you can have function definitions containing a prototype... but in this case there's no point in using "extern".
[toc] | [prev] | [next] | [standalone]
| From | "James R. Kuyper" <jameskuyper@verizon.net> |
|---|---|
| Date | 2017-02-13 14:24 -0500 |
| Message-ID | <8cb27dfb-9d35-e77d-34c0-a4a7e5cd017f@verizon.net> |
| In reply to | #103813 |
On 02/13/2017 11:24 AM, GOTHIER Nathan wrote: > On Mon, 13 Feb 2017 15:16:07 +0100 > David Brown <david.brown@hesbynett.no> wrote: > >> No. Prototypes are usually in advance of the definition, not /after/ >> the definition (assuming the definition is in the same TU as the >> prototype in question). And if you have a "static" function definition, >> it is perfectly reasonable to have a "static" prototype for it in >> advance of the function definition - you do that if you have mutually >> recursive static functions, or if you just prefer a different order for >> defining your functions. > > I'm amazed how you make things right using corner cases... Your quest for the > only one truth show your devotion as a good Christian. :-) Having a function definition precede a function prototype for the same function is a real corner case. Such a function prototype, which you described as the norm, is completely unnecessary if the function definition itself uses prototype syntax, and I can't recall ever seeing code containing such a prototype. > Usually prototypes are used to access definitions provided to the linker as a > library. They're also used to access definitions provided to the linker as stand-alone object files. Most prototypes that I actually write fall into this category - the library function prototypes are generally written by whoever implements the library.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-02-13 23:29 +0100 |
| Message-ID | <o7tbt6$74t$1@dont-email.me> |
| In reply to | #103813 |
On 13/02/17 17:24, GOTHIER Nathan wrote:
> On Mon, 13 Feb 2017 15:16:07 +0100 David Brown
> <david.brown@hesbynett.no> wrote:
>
>> No. Prototypes are usually in advance of the definition, not
>> /after/ the definition (assuming the definition is in the same TU
>> as the prototype in question). And if you have a "static" function
>> definition, it is perfectly reasonable to have a "static" prototype
>> for it in advance of the function definition - you do that if you
>> have mutually recursive static functions, or if you just prefer a
>> different order for defining your functions.
>
> I'm amazed how you make things right using corner cases...
The most common use of function prototypes is in the function definition:
// mod.c
static double foo(int a, double b) { return a * b; }
A second common use is in both a declaration, and the definition. The
declaration is put in a header:
// mod.h
extern double foo(int a, double b);
// or omit the "extern" if you prefer
// mod.c
#include "mod.h"
double foo(int a, double b) { return a * b; }
The third common use is in both a declaration and the definition, for
"forward declarations" so that you can call the function before it is
defined:
// mod.c
#include "mod.h"
static double foo(int a, double b);
static foo(int a, double b) { return a * b; }
Note that in most of these cases, the prototype is "static". Only in
the case of a header declaration is it "extern", and even then the
"extern" keyword is optional (I like to use it, but I can't say how
common that is).
Giving a prototype /after/ the definition of a function is basically
useless - it might be done by a weird accident of how code is arranged,
but it is not going to be done intentionally.
So in no sense do prototypes point to "a previous definition".
> Your quest
> for the only one truth show your devotion as a good Christian. :-)
>
I can't figure out any meaning from that sentence, but I get the vague
feeling you are trying to be insulting, or at least critical. I won't
take offence - I will simply assure you that you are probably wrong.
> Usually prototypes are used to access definitions provided to the
> linker as a library.
No. Prototypes are used to tell the compiler the "signature" of a
function - it's name, qualifiers, parameters and return type. That
applies to /all/ functions, whether they are static to a file, shared
across translation units, or as part of a library.
> Sometimes you can have function definitions
> containing a prototype...
Any function written since C90 was introduced should have a prototype as
part of its definition - non-prototype function definitions are long
outdated.
> but in this case there's no point in using
> "extern".
>
That part is true. It is seldom that you see a function definition
marked "extern" - you usually have the "extern" prototype in a header
file separate from the function definition.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-02-13 11:06 -0800 |
| Message-ID | <ln37fhuczz.fsf@kst-u.example.com> |
| In reply to | #103790 |
GOTHIER Nathan <nathan.gothier@gmail.com> writes:
[...]
> Prototypes should always be declared as "extern" since it points to a previous
> definition.
In what sense is the definition necessarily "previous", and why would
that argue in favor of using "extern"?
At file scope, this:
extern void foo(void);
and this:
void foo(void);
mean exactly the same thing. I don't object to adding the "extern"
keyword if you think it makes it clearer, but it's not required.
--
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 | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2017-02-13 11:15 -0800 |
| Message-ID | <o7t0gl$ntb$1@dont-email.me> |
| In reply to | #103790 |
On 2/13/2017 4:44 AM, GOTHIER Nathan wrote: > > Prototypes should always be declared as "extern" since it points to a previous > definition. > Why? The purpose of 'extern' is to give an entity *external linkage*. Since functions in C have external linkage by default, there's never any reason to use 'extern' with functions in C, regardless of whether it is a prototype, declaration or definition. The only exception from this is probably the 'extern inline' combination. -- Best regards, Andrey Tarasevich
[toc] | [prev] | [next] | [standalone]
| From | "James R. Kuyper" <jameskuyper@verizon.net> |
|---|---|
| Date | 2017-02-13 11:48 -0500 |
| Message-ID | <c4640aea-d7df-a409-581b-0513a47cf729@verizon.net> |
| In reply to | #103789 |
On 02/13/2017 07:14 AM, David Brown wrote: ... > Personally, I also put "extern" in my function declarations in headers. > It is not required (since the lack of a function body already marks it > as a non-defining declaration), and many people don't use it, but I feel > it gives a clearer indication that this is a "global" function. "If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern." (6.2.2p5) The absence of a storage-class specifier should, therefore, be precisely as clear an indication as an explicit "extern" specifier.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-02-13 09:03 -0800 |
| Message-ID | <9390bc20-8824-44e5-8697-735e4b1ba264@googlegroups.com> |
| In reply to | #103815 |
On Monday, February 13, 2017 at 10:48:26 AM UTC-6, James R. Kuyper wrote: > "If the declaration of an identifier for a function has no storage-class > specifier, its linkage is determined exactly as if it were declared with > the storage-class specifier extern." (6.2.2p5) > The absence of a storage-class specifier should, therefore, be precisely > as clear an indication as an explicit "extern" specifier. It is precisely as clear with respect to how a compiler will interpret it. That does not imply, however, that there would not be advantages to including extern as a message to *humans* that the function is not going to be defined in its usual spot (e.g. if a C source file is intended to be used with an assembly-language module, and the functions in that module will only be called from within that source file, I would likely apply an "extern" qualifier to their declarations).
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-02-13 23:37 +0100 |
| Message-ID | <o7tcc7$8no$1@dont-email.me> |
| In reply to | #103815 |
On 13/02/17 17:48, James R. Kuyper wrote: > On 02/13/2017 07:14 AM, David Brown wrote: > ... >> Personally, I also put "extern" in my function declarations in headers. >> It is not required (since the lack of a function body already marks it >> as a non-defining declaration), and many people don't use it, but I feel >> it gives a clearer indication that this is a "global" function. > > "If the declaration of an identifier for a function has no storage-class > specifier, its linkage is determined exactly as if it were declared with > the storage-class specifier extern." (6.2.2p5) > The absence of a storage-class specifier should, therefore, be precisely > as clear an indication as an explicit "extern" specifier. As far as the compiler is concerned, that is true. But many C programmers have not read the standards, and may not find it as obvious - putting "extern" here makes the purpose of the prototype clear and explicit. Perhaps it is merely my own habit of how I like to write code. I also prefer to write "long int" rather than "long", even though the "int" part is not necessary. I like to add some spaces and brackets that are unnecessary - it's the way I write my code. But I have no complaints about code that does not use "extern" here - it's perfectly clear to /me/ what it means.
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2017-02-10 15:40 -0800 |
| Message-ID | <o7liua$o6o$1@dont-email.me> |
| In reply to | #103643 |
On 2/10/2017 3:24 PM, BartC wrote:
>
> Sure all that's needed is a Local, Imported, Exported model?
>
But that's actually already a viable way to perceive 'extern'.
* When 'extern' is used in an external *definition*, it means
"exported".
Examples:
extern int i = 42; // Definition, since it includes an initializer
extern void foo(void) // Definition, since it includes a body
{
...
}
* When 'extern' is applied to an external non-defining *declaration*,
it means "imported".
Examples:
extern int i; // Non-defining declaration
extern void foo(void); // Non-defining declaration
Granted, in most of these examples 'extern' is redundant. But that's a
different story.
P.S. In C++ 'extern' becomes non-redundant when used with 'const' object
definitions, since in C++ 'const' objects have internal linkage by default
// C++
extern const int i = 42;
// Definition, since it includes an initializer
// This definition is explicitly "exported" by this 'extern', since
// otherwise it would have been invisible to the external world
--
Best regards,
Andrey Tarasevich
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-02-13 05:09 -0800 |
| Message-ID | <kfn37fi2q58.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #103643 |
BartC <bc@freeuk.com> writes: > On 10/02/2017 22:53, Andrey Tarasevich wrote: >> On 2/10/2017 9:16 AM, BartC wrote: > [..regarding use of 'extern'..] > > The 'extern' method is what I use exclusively when my tools > auto-generate C code, as it's the method that more closely matches > how I think about it: > > static int A [= expr]; // Defined here, not exported > int B [= expr]; // Defined here, exported > extern int C; // Defined elsewhere, imported > > [...] > > Using headers like normal C code, it might be more like this: > > X sees: extern int B; // from #include "X.h" > X contains: int B; // > > Y sees: extern int B; // from #include "X.h" > Z sees: extern int B; // from #include "X.h" This pattern, or one very similar to it, is used by all sensible C programmers. > This combination I can understand. However no one else seems to > write C like I do!) Lots of people do write C using a pattern like the one you show above. Is it really true that you don't see that in any of the C code you look at that is written by other people? If so it would be interesting to know what programs those are, they sound unusual to say the least.
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-02-13 13:46 +0000 |
| Message-ID | <o7sd8q$enk$1@dont-email.me> |
| In reply to | #103793 |
On 13/02/2017 13:09, Tim Rentsch wrote:
> BartC <bc@freeuk.com> writes:
>> X sees: extern int B; // from #include "X.h"
>> X contains: int B; //
>>
>> Y sees: extern int B; // from #include "X.h"
>> Z sees: extern int B; // from #include "X.h"
>
> This pattern, or one very similar to it, is used by all sensible
> C programmers.
>
>> This combination I can understand. However no one else seems to
>> write C like I do!)
>
> Lots of people do write C using a pattern like the one you show
> above. Is it really true that you don't see that in any of the C
> code you look at that is written by other people? If so it would
> be interesting to know what programs those are, they sound
> unusual to say the least.
Actually it's difficult to tell, since a lot of examples I've just
looked at hide declarations behind horrendous looking multi-level
macros. So CPython's 40,000 lines of headers only have some 60
occurrences of plain 'extern'.
At least, gcc's stdio.h seems to use them directly:
extern
__attribute__((__format__ (gnu_printf, 3, 0))) __MINGW_ATTRIB_NONNULL(3)
int __cdecl __mingw_vsnprintf(char * __restrict__ _DstBuf,size_t
_MaxCount,const char * __restrict__ _Format,
va_list _ArgList);
Lovely code. I assume this is only declaring one function, it's hard to
tell! But it's still code abuse IMO.
--
bartc
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-02-13 09:52 -0800 |
| Message-ID | <ln7f4ut1va.fsf@kst-u.example.com> |
| In reply to | #103799 |
BartC <bc@freeuk.com> writes:
[...]
> At least, gcc's stdio.h seems to use them directly:
gcc has no stdio.h
> extern
> __attribute__((__format__ (gnu_printf, 3, 0))) __MINGW_ATTRIB_NONNULL(3)
> int __cdecl __mingw_vsnprintf(char * __restrict__ _DstBuf,size_t
> _MaxCount,const char * __restrict__ _Format,
> va_list _ArgList);
That appears to be provided by MinGW, not gcc. I have a gcc-based
implementation on my system, and it doesn't include that declaration.
> Lovely code. I assume this is only declaring one function, it's hard to
> tell! But it's still code abuse IMO.
--
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 | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-02-13 19:19 +0000 |
| Message-ID | <o7t0ns$pnt$1@dont-email.me> |
| In reply to | #103821 |
On 13/02/2017 17:52, Keith Thompson wrote: > BartC <bc@freeuk.com> writes: > [...] >> At least, gcc's stdio.h seems to use them directly: > > gcc has no stdio.h If I look inside my gcc implementation's stdio.h that it uses to compile C under Windows, then that's what it has. I didn't put it there or knowingly download it, and it has different content from the stdio.h of any other non-gcc compiler. >> extern >> __attribute__((__format__ (gnu_printf, 3, 0))) __MINGW_ATTRIB_NONNULL(3) >> int __cdecl __mingw_vsnprintf(char * __restrict__ _DstBuf,size_t >> _MaxCount,const char * __restrict__ _Format, >> va_list _ArgList); > > That appears to be provided by MinGW, not gcc. I have a gcc-based > implementation on my system, and it doesn't include that declaration. Since gcc apparently supports 1000 different platforms, that's not surprising. If I have a file that #includes 22 standard C headers, then that involves 44 different headers (including nested) on gcc/Windows, and 80 different ones on gcc/Linux. It's a mystery why gcc-related headers seem to be so full of junk compared with those of other compilers. >> Lovely code. I assume this is only declaring one function, it's hard to >> tell! But it's still code abuse IMO. This is what that function declares: extern vsnprintf(char*, size_t, char*, va_list); I think, beyond being in text format, they've given up on making this stuff human-readable. Or tidy and compact. If there was a need to impart extra information about this function that has special meaning when compiled with gcc, then there are more elegant ways of doing it that leaves the main declaration uncluttered. -- bartc
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-02-13 11:34 -0800 |
| Message-ID | <lny3x9sx46.fsf@kst-u.example.com> |
| In reply to | #103828 |
BartC <bc@freeuk.com> writes:
> On 13/02/2017 17:52, Keith Thompson wrote:
>> BartC <bc@freeuk.com> writes:
>> [...]
>>> At least, gcc's stdio.h seems to use them directly:
>>
>> gcc has no stdio.h
>
> If I look inside my gcc implementation's stdio.h that it uses to compile
> C under Windows, then that's what it has. I didn't put it there or
> knowingly download it, and it has different content from the stdio.h of
> any other non-gcc compiler.
I've explained this multiple times. Don't pretend you don't understand.
[...]
> This is what that function declares:
>
> extern vsnprintf(char*, size_t, char*, va_list);
No, the name of the function it declares (assuming I'm understanding the
non-standard parts well enough) is "__mingw_vsnprintf", not "vsnprintf".
I presume they're rather closely related.
The standard, or a man page, or a C reference will tell you, as a
programmer, all you need to know about the vsnprintf function, whose
declaration is actually:
int vsnprintf(char * restrict s, size_t n, const char * restrict format, va_list arg);
> I think, beyond being in text format, they've given up on making this
> stuff human-readable. Or tidy and compact.
And why is that a bad thing? Are you relying on system headers as
documentation? That's not what they're for. What would be the benefit
of the extra work that would be required to make them easily
human-readable?
> If there was a need to impart extra information about this function that
> has special meaning when compiled with gcc, then there are more elegant
> ways of doing it that leaves the main declaration uncluttered.
Why does it matter what the declaration of __mingw_vsnprintf looks like?
Are you ever going to call it?
--
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 | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-02-13 20:13 +0000 |
| Message-ID | <o7t3uk$79j$1@dont-email.me> |
| In reply to | #103831 |
On 13/02/2017 19:34, Keith Thompson wrote: > BartC <bc@freeuk.com> writes: > Why does it matter what the declaration of __mingw_vsnprintf looks like? > Are you ever going to call it? It hurts my eyes. I means, how many pages of gobbledygook does it take to define one function, before anyone here says, Hang on, what the hell's this all in aid of? -- bartc
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2017-02-13 13:11 -0800 |
| Message-ID | <o7t7ad$lko$1@dont-email.me> |
| In reply to | #103828 |
On 2/13/2017 11:19 AM, BartC wrote:
>
> This is what that function declares:
>
> extern vsnprintf(char*, size_t, char*, va_list);
>
You lost the 'int' somehow.
And, on a related note:
C89/90 grammar prohibits declarations without 'declaration-specifiers'
(as opposed to K&R, which apparently allowed it). This means that in
order to take advantage of the "implicit int" rule in C89/90, you
formally have to include at least a 'storage-class-specifier' or
'type-qualifier' into each declaration. I.e. in C89/90 you cannot just
declare
foo(void);
you have to have something before 'foo', like
extern foo(void);
/* or */
static bar(void);
/* or */
const baz(void);
Since the above 'extern' is completely inconsequential, the above
illustrates a credible application of an explicit 'extern' in function
declarations in C89/90: to serve as a "dummy" token that fills the
non-empty 'declaration-specifiers' requirement in situations when you
for some reason want to use the "implicit int" rule.
--
Best regards,
Andrey Tarasevich
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-02-14 00:33 +0100 |
| Message-ID | <o7tfl8$lta$1@dont-email.me> |
| In reply to | #103828 |
On 13/02/17 20:19, BartC wrote: > On 13/02/2017 17:52, Keith Thompson wrote: >> BartC <bc@freeuk.com> writes: >> [...] >>> At least, gcc's stdio.h seems to use them directly: >> >> gcc has no stdio.h > > If I look inside my gcc implementation's stdio.h that it uses to compile > C under Windows, then that's what it has. I didn't put it there or > knowingly download it, and it has different content from the stdio.h of > any other non-gcc compiler. > >>> extern >>> __attribute__((__format__ (gnu_printf, 3, 0))) >>> __MINGW_ATTRIB_NONNULL(3) >>> int __cdecl __mingw_vsnprintf(char * __restrict__ _DstBuf,size_t >>> _MaxCount,const char * __restrict__ _Format, >>> va_list _ArgList); >> >> That appears to be provided by MinGW, not gcc. I have a gcc-based >> implementation on my system, and it doesn't include that declaration. > > Since gcc apparently supports 1000 different platforms, that's not > surprising. If I have a file that #includes 22 standard C headers, then > that involves 44 different headers (including nested) on gcc/Windows, > and 80 different ones on gcc/Linux. > > It's a mystery why gcc-related headers seem to be so full of junk > compared with those of other compilers. Basically, what you are saying is "I don't understand this. Therefore it must be junk". I don't know whether you are too lazy to look it up, or scared that you won't understand what you read, or merely worried that if you actually learn what this means then you will lose some opportunities to moan about gcc. First, you have to realise that this is a library, it is not part of gcc. It is written in a way that will work with many compilers (hence some macros are used), but that it should be as optimal as possible across a wide range of gcc versions (and compiler flags) since it is most commonly used with gcc. It also aims to give as good static error checking as possible. This it uses "__restrict__", which will work like "restrict" on C99 for more efficient code generation - but will also work on gcc with other choices of standards and in C++. It has the "format" attribute, to give error checking - gcc can warn you if your printf format does not match with the actual parameters (for a fixed format string). It is all useful stuff. > > >>> Lovely code. I assume this is only declaring one function, it's hard to >>> tell! But it's still code abuse IMO. > > This is what that function declares: > > extern vsnprintf(char*, size_t, char*, va_list); > > I think, beyond being in text format, they've given up on making this > stuff human-readable. Or tidy and compact. Yes, but the version from the library you gave does more. It is also more informative (the parameters have names), and it is correct (it has a return type). > > If there was a need to impart extra information about this function that > has special meaning when compiled with gcc, then there are more elegant > ways of doing it that leaves the main declaration uncluttered. >
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-02-14 01:02 +0000 |
| Message-ID | <o7tkra$4al$1@dont-email.me> |
| In reply to | #103852 |
On 13/02/2017 23:33, David Brown wrote:
> On 13/02/17 20:19, BartC wrote:
>> It's a mystery why gcc-related headers seem to be so full of junk
>> compared with those of other compilers.
>
> Basically, what you are saying is "I don't understand this. Therefore
> it must be junk". I don't know whether you are too lazy to look it up,
Why would I want to look it up? Look at the lccwin or MSDN versions
below; /that's/ how you want these things expressed. Short and sweet. (I
don't want to think about what your own headers look like if you think
this is reasonable.)
> or scared that you won't understand what you read, or merely worried
> that if you actually learn what this means then you will lose some
> opportunities to moan about gcc.
>
> First, you have to realise that this is a library, it is not part of
> gcc. It is written in a way that will work with many compilers (hence
> some macros are used),
I tried that header with 4 other compilers (compiling hello world with
the include search path set to the one used by this gcc), and they all
failed.
but that it should be as optimal as possible
> across a wide range of gcc versions (and compiler flags) since it is
> most commonly used with gcc. It also aims to give as good static error
> checking as possible.
> This it uses "__restrict__", which will work like "restrict" on C99 for
> more efficient code generation - but will also work on gcc with other
> choices of standards and in C++. It has the "format" attribute, to give
> error checking - gcc can warn you if your printf format does not match
> with the actual parameters (for a fixed format string).
lccwin also does that checking; /its/ vsnprintf looks like this:
int vsnprintf(char *,size_t,const char *,va_list);
(How on earth does it manage that?)
You seem to constantly think that things that are bigger and more
complicated are always better and always justified.
>>
>> This is what that function declares:
>>
>> extern vsnprintf(char*, size_t, char*, va_list);
>>
>> I think, beyond being in text format, they've given up on making this
>> stuff human-readable. Or tidy and compact.
>
> Yes, but the version from the library you gave does more. It is also
> more informative (the parameters have names),
This is the same function in the MSDN docs, and the params have names:
int vsnprintf(
char *buffer,
size_t count,
const char *format,
va_list argptr
);
>and it is correct (it has a return type).
Yes, the int. Maybe I was using 'implicit' int, or maybe I missed a
3-letter return type lurking somewhere in the /middle/ of all that
line-noise.
If implementers don't want this to be readable, then why bother having
it as source code? That must be reprocessed over and over again. There
must be more efficient ways of doing it, and AFAIK C doesn't stop an
implementation from having standard headers inside the compiler already
built-in.
--
bartc
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-02-14 09:28 +0100 |
| Message-ID | <o7uf0l$s1d$1@dont-email.me> |
| In reply to | #103854 |
On 14/02/17 02:02, BartC wrote:
> On 13/02/2017 23:33, David Brown wrote:
>> On 13/02/17 20:19, BartC wrote:
>
>>> It's a mystery why gcc-related headers seem to be so full of junk
>>> compared with those of other compilers.
>>
>> Basically, what you are saying is "I don't understand this. Therefore
>> it must be junk". I don't know whether you are too lazy to look it up,
>
> Why would I want to look it up?
You must have had some interest in the details to look up the function's
declaration in the header file - otherwise you would do what everyone
else does, and use a more practical reference for the vsnprintf
function, such as:
<http://en.cppreference.com/w/c/io/vfprintf>
So you are interested in how it is declared, yet now you are saying that
you are not interested in what these details mean. Was your only
purpose in looking it up and posting it so that you can mock something
you don't understand?
> Look at the lccwin or MSDN versions
> below; /that's/ how you want these things expressed. Short and sweet. (I
> don't want to think about what your own headers look like if you think
> this is reasonable.)
I don't have lccwin or MSDN, and have no interest in them - so no, I
won't look that up. You posted lccwin's version and it is far inferior
for a library call. It does not follow the standards (at least, not C99
onwards), it does not name the parameters, it provides no extra
information to the compiler for optimisation usage (maybe lccwin simply
does not have the same kind of optimisations), and it does not provide
information to allow the kind of extremely useful format checking
features of gcc.
As for my own headers, you are apparently totally misunderstanding the
difference between basic libraries and user code. Let me explain.
User code is written by the user. It must follow the
implementation-defined rules of C (i.e., the language defined by the
standards along with any implementation-specific features). It should
be written to be readable and maintainable, with the user's choice of
balance between development time, clarity, run-time efficiency, etc. It
can be written to work with lots of compilers or just one, many compiler
options or just one set, many C standards or just one.
Standard library code is part of the implementation. Even if it is
developed separately from the compiler, it is still in close cooperation
with the compiler. It does not have to follow the rules - it can
"cheat", as long as the compiler is in on the game - the library writer
can put things in the headers and implementation files that are not
allowed in user code. It is written by a few people, but used by
millions - the emphasis is very solidly on the side of run-time
efficiency rather than developer efficiency. It must work regardless of
the compiler options, and usually regardless of the compiler version -
sometimes regardless of the compiler vendor. It typically must work
regardless of the language, supporting C and C++ and possibly others
such as Objective-C. And it must match the standards exactly.
So /I/ would be very unlikely to have as much complications in a
declaration as this one does. (If I were writing a printf-style
function, I /would/ use the "format" attribute.) Most of my
declarations are relatively simple in practice, though I would never
write the lazy way of lccwin's declaration without parameter names.
However, I would expect to see a different level entirely in a standard
library header - the example you gave looks like it is from someone who
does not care about what he is doing.
(Note - because the compiler and the library work together to form the
implementation, it is quite possible for them to have extra hidden
features that are not apparent in the declarations in the headers. The
compiler can quite reasonably assume that the "restrict" qualifiers are
in the right places, or know about checking format strings for the
printf family even though it is not expressed in the header. I am only
commenting on the single declaration you quoted - lccwin may be more
advanced than that declaration suggests.)
>
>> or scared that you won't understand what you read, or merely worried
>> that if you actually learn what this means then you will lose some
>> opportunities to moan about gcc.
>>
>> First, you have to realise that this is a library, it is not part of
>> gcc. It is written in a way that will work with many compilers (hence
>> some macros are used),
>
> I tried that header with 4 other compilers (compiling hello world with
> the include search path set to the one used by this gcc), and they all
> failed.
If you look at the name of the function, it is "__mingw_vsnprintf". You
will probably find that "vsnprintf" is declared elsewhere, or perhaps
there are weak symbols, aliases, or other compiler-library interactions.
I don't know whether this particular library will work on other
compilers, but certainly some libraries are portable between compilers.
The choice of compilers will, of course, be limited - a standard
library is part of the implementation. It may work with clang, for example.
>
> but that it should be as optimal as possible
>> across a wide range of gcc versions (and compiler flags) since it is
>> most commonly used with gcc. It also aims to give as good static error
>> checking as possible.
>> This it uses "__restrict__", which will work like "restrict" on C99 for
>> more efficient code generation - but will also work on gcc with other
>> choices of standards and in C++. It has the "format" attribute, to give
>> error checking - gcc can warn you if your printf format does not match
>> with the actual parameters (for a fixed format string).
>
> lccwin also does that checking; /its/ vsnprintf looks like this:
>
> int vsnprintf(char *,size_t,const char *,va_list);
>
> (How on earth does it manage that?)
The "vsnprintf" function is defined in the standard - the compiler knows
what it should do, and can check the format string. Whether it does
that or not, I don't know.
int main(void) {
int a = 1;
const char* s = "Hello";
printf("Text: %s Data: %i\n", a, s);
}
With -Wall, gcc will warn that "%s" expects an argument of type "char*",
but argument 2 has type "int".
Does lccwin do that kind of checking? As I say, it is perfectly
possible for the compiler to manage this without it being in the header.
But gcc chose to implement this using function attributes. This means
it works fine with various language standards, or with libraries with
extra features. It also works with user code - I can define a
"debugPrintf" or "uartPrintf" function and get the same kind of checking.
>
> You seem to constantly think that things that are bigger and more
> complicated are always better and always justified.
>
>>>
>>> This is what that function declares:
>>>
>>> extern vsnprintf(char*, size_t, char*, va_list);
>>>
>>> I think, beyond being in text format, they've given up on making this
>>> stuff human-readable. Or tidy and compact.
>>
>> Yes, but the version from the library you gave does more. It is also
>> more informative (the parameters have names),
>
> This is the same function in the MSDN docs, and the params have names:
>
> int vsnprintf(
> char *buffer,
> size_t count,
> const char *format,
> va_list argptr
> );
Parameter names are an improvement, but the declaration is still wrong
for C99 onwards. And again, it does not have the extra static error
checking features (again, these may be built into the compiler).
>
>>and it is correct (it has a return type).
>
> Yes, the int. Maybe I was using 'implicit' int, or maybe I missed a
> 3-letter return type lurking somewhere in the /middle/ of all that
> line-noise.
The "line-noise" in question was the declaration from lccwin... But
yes, I realise that was probably a typo.
However, the declaration from the standards (C99, C11) is:
int vsnprintf(char * restrict s, size_t n,
const char * restrict format,
va_list arg);
Note the "restrict" part. It is a /long/ time since C99 was standard.
The gcc use of "__restrict__", which you see as ugly, complex, and
apparently difficult to understand, lets that declaration work in C90
mode and in C++ (where gcc supports it as an extension).
>
> If implementers don't want this to be readable, then why bother having
> it as source code? That must be reprocessed over and over again. There
> must be more efficient ways of doing it, and AFAIK C doesn't stop an
> implementation from having standard headers inside the compiler already
> built-in.
>
It is perfectly readable, to anyone who wants to make a small effort to
/read/ it rather than to complain about it. The compiler is quite happy
with it.
You are right that a compiler can have some or all of the information
about the library headers and implementation built-in. Some do. You
are also right that this could make an implementation a good deal more
efficient. gcc does not do this - it has /knowledge/ of the compiler
library built in, and can turn some printf() calls into puts(), and
inlines memcpy() and optimises str* functions. But most of the library
and headers are external for maximum flexibility - people use many
different libraries with gcc.
[toc] | [prev] | [next] | [standalone]
Page 3 of 6 — ← Prev page 1 2 [3] 4 5 6 Next page →
Back to top | Article view | comp.lang.c
csiph-web