inline trouble with -std=gnu99 (gcc)

  • Follow


Hi,

me again.
This "project" (lol) compiles without any warnings if -std=gnu99 is NOT 
specified.
However, once it is specified, the inline function is treated as if not 
there.

line:
gcc -o a.exe -O2 -Wall -std=gnu99 misc.c menu.c main.c

As I learned it long ago, the order of the translation units DOES matter.
Thus, if I have
[misc.c] inline void shortfunc(USHORT x) { ... }
I may use
[menu.c] extern inline void shortfunc(USHORT);

However, this causes major trouble with gnu99 standard.

Here's my code: (sorry 6 files)

--------
[misc.c]
--------
#include "misc.h"
inline void strToUpper (char* s)
{
 while (*s)
 {
     if(*s > 96 && *s<123)
     *s-=32;
     s++;
 }
}
--------
[misc.h]
--------
ULONG somevariable;

--------
[main.c]
--------
#include "main.h"

int main(int argc, char* argv[])
{  return 0; }
--------
[main.h]
--------
/* here's the troublesome extern inline reference, PREVIOUSLY defined in 
misc.c */
extern inline void strToUpper (char*);

--------
[menu.c]
--------
#include "menu.h"
void dummy (void)
{ }

--------
[menu.h]
--------
/* adfmenu.h */
extern inline void strToUpper (char*);

-----
OK, that's it so far...
And now I get: (line numbers removed because they may vary)

menu.h: warning: inline function 'strToUpper' declared but never defined
menu.h: warning: inline function 'strToUpper' declared but never defined
main.h: warning: inline function 'strToUpper' declared but never defined
main.h: warning: inline function 'strToUpper' declared but never defined

"Never defined"? Well, there IS some code in strToUpper(), so this warning 
is keeping me puzzled...

Thanks for any insights.

-Andreas 

0
Reply aeibach1 (47) 10/6/2009 6:55:19 AM

On 6 Oct, 07:55, "Andreas Eibach" <aeib...@mail.com> wrote:

> This "project" (lol) compiles without any warnings if -std=3Dgnu99 is NOT
> specified.

so, presumably, you're deploying gcc as a C89 compiler...

> However, once it is specified, the inline function is treated as if not
> there.

C89 doesn't have inline functions

> line:
> gcc -o a.exe -O2 -Wall -std=3Dgnu99 misc.c menu.c main.c
>
> As I learned it long ago, the order of the translation units DOES matter.

I thought you weren't going to use C99?

how peculiar. Preumably that specifies the order to the linker. (I
never
use gcc this way. I compile each .c to a .o the link all the .o's
together)

> Thus, if I have
> [misc.c] inline void shortfunc(USHORT x) { ... }
> I may use
> [menu.c] extern inline void shortfunc(USHORT);
>
> However, this causes major trouble with gnu99 standard.

extern inline seems very odd to me...

> Here's my code: (sorry 6 files)
>
> --------
> [misc.c]
> --------
> #include "misc.h"
> inline void strToUpper (char* s)
> {
> =A0while (*s)
> =A0{
> =A0 =A0 =A0if(*s > 96 && *s<123)
> =A0 =A0 =A0*s-=3D32;
> =A0 =A0 =A0s++;
> =A0}}

this may be a peculiarity of C99 (or gcc) but my experience of inline
is C++ and I wouldn't put an inline function in a separate C file.
I'd expect the inline function to be visible in the compilation
unit.
How else could the compiler inline the code?


> --------
> [misc.h]
> --------
> ULONG somevariable;
>
> --------
> [main.c]
> --------
> #include "main.h"
>
> int main(int argc, char* argv[])
> { =A0return 0; }
> --------
> [main.h]
> --------
> /* here's the troublesome extern inline reference, PREVIOUSLY defined in
> misc.c */

I'm not even sure what "extern inline" means

> extern inline void strToUpper (char*);
>
> --------
> [menu.c]
> --------
> #include "menu.h"
> void dummy (void)
> { }
>
> --------
> [menu.h]
> --------
> /* adfmenu.h */
> extern inline void strToUpper (char*);
>
> -----
> OK, that's it so far...
> And now I get: (line numbers removed because they may vary)
>
> menu.h: warning: inline function 'strToUpper' declared but never defined
> menu.h: warning: inline function 'strToUpper' declared but never defined
> main.h: warning: inline function 'strToUpper' declared but never defined
> main.h: warning: inline function 'strToUpper' declared but never defined
>
> "Never defined"? Well, there IS some code in strToUpper(), so this warnin=
g
> is keeping me puzzled...
>
> Thanks for any insights.

put the code in the header file. At the very least peruse a good C99
tutorial (H&S? The Standard?) and check how inline is supposed to be
used.


0
Reply nick_keighley_nospam (4574) 10/6/2009 7:16:26 AM


"Andreas Eibach" <aeibach@mail.com> writes:
> Hi,
>
> me again.
> This "project" (lol) compiles without any warnings if -std=gnu99 is
> NOT specified.
> However, once it is specified, the inline function is treated as if
> not there.
....

> --------
> [misc.h]
> --------
> ULONG somevariable;

Don't do that, it's dumb. Declare but don't define, variables in 
header files;

> --------
> [main.h]
> --------
> /* here's the troublesome extern inline reference, PREVIOUSLY defined
> in misc.c */
> extern inline void strToUpper (char*);

Don't make baseless assertions - it's not previously defined in misc.c. 
It's *subsequently* defined in misc.c from misc.c's perspective.

And quite what do you mean by a function being 'extern inline'? 
What does gcc mean by it? And, for completeness, ISO C?

> Thanks for any insights.

a) Don't do dumb things.
b) Google for ``extern inline gcc''.

Phil
-- 
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1
0
Reply thefatphil_demunged (1558) 10/6/2009 7:24:47 AM


"Phil Carmody" <thefatphil_demunged@yahoo.co.uk> wrote:
>> --------
>> [misc.h]
>> --------
>> ULONG somevariable;
>
> Don't do that, it's dumb. Declare but don't define, variables in
> header files;

yeah, well, I normally do not do this. But what did you else want to have?
Some other #include statements? ;-) I've tried to break down the code to the 
fundamentals.
So I just put in something for the fun of it, so that it's not empty, 
yeah...
Maybe I should have pondered a little more about what to actually put in 
there, but wth ^_^

-Andreas 

0
Reply aeibach1 (47) 10/6/2009 7:37:56 AM

Andreas Eibach wrote:
> "Phil Carmody" <thefatphil_demunged@yahoo.co.uk> wrote:
>>> --------
>>> [misc.h]
>>> --------
>>> ULONG somevariable;
>> 
>> Don't do that, it's dumb. Declare but don't define, variables in
>> header files;
> 
> yeah, well, I normally do not do this. But what did you else want to
> have? Some other #include statements? ;-) I've tried to break down
> the code to the fundamentals.
Perhaps this is better :

[misc.h]
extern ULONG somevariable;

[misc.c]
ULONG somevariable = some_default_value;

-- 
Mark
0
Reply mark_cruzNOTFORSPAM (178) 10/6/2009 8:26:19 AM

In <7j07nmF31sgsgU1@mid.uni-berlin.de>, Andreas Eibach wrote:

> Hi,
> 
> me again.
> This "project" (lol) compiles without any warnings if -std=gnu99 is
> NOT specified.
> However, once it is specified, the inline function is treated as if
> not there.

Probably just as well.

Others are already dealing with your inlining issues, so I'd like to 
offer an alternative perspective:

> Here's my code: (sorry 6 files)

Here's something a bit better (3 files):

/* xstring.h */
#ifndef H_XSTRING_
#define H_XSTRING_ 1
void upstring(char *);
#endif

/* xstring.c */
#include "xstring.h"
#include <ctype.h>
void upstring(char *s)
{
  while(*s != '\0')
  {
    *s = toupper((unsigned char)*s);
    s++;
  }
}

/* main.c */
#include "xstring.h"
#include <stdio.h>

int main(int argc, char* argv[])
{
  while(argc--)
  {
    upstring(argv[argc]);
    printf("%s\n", argv[argc]);
  }
  return 0;
}

Note the improvements:

(a) half the input files of your version;
(b) library function name is easier to type and remember;
(c) no troublesome diagnostics;
(d) portability to C90;
(e) removal of reliance on ASCII-derived character set;
(f) actual functionality added;
(g) only took about 90 seconds to write.

<snip>

-- 
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
0
Reply rjh (10789) 10/6/2009 8:49:42 AM

On 6 oct, 10:49, Richard Heathfield <r...@see.sig.invalid> wrote:
> /* xstring.h */
> #define H_XSTRING_ 1

Hi Richard, is neccessary to write 1 in H_XSTRING 1?
0
Reply davranfor (97) 10/6/2009 9:35:45 AM

In 
<b1360ba2-c510-44a7-a7ef-38eced0ef155@o21g2000vbl.googlegroups.com>, 
David RF wrote:

> On 6 oct, 10:49, Richard Heathfield <r...@see.sig.invalid> wrote:
>> /* xstring.h */
>> #define H_XSTRING_ 1
> 
> Hi Richard, is neccessary to write 1 in H_XSTRING 1?

No. It does, however, offer you slightly more flexibility, as it 
allows you to use different values for different (mutually exclusive) 
purposes. I don't think I've ever actually taken advantage of this, 
but I might, one day. Maybe. The main reason I do it is a rather weak 
one - I think it /looks/ better for H_XSTRING to have a value.

-- 
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
0
Reply rjh (10789) 10/6/2009 9:45:38 AM


"Mark" <mark_cruzNOTFORSPAM@hotmail.com> wrote:
> Perhaps this is better :
>
> [misc.h]
> extern ULONG somevariable;
>
> [misc.c]
> ULONG somevariable = some_default_value;
>
Nah!

I always use "extern" *across files* (e. g. misc.c <-> main.c) but never 
between a header and a main file with the same prefix (misc.h<->misc.c)
At least I never did before.

-Andreas 

0
Reply aeibach1 (47) 10/6/2009 4:52:41 PM

"Andreas Eibach" <aeibach@mail.com> writes:

> "Mark" <mark_cruzNOTFORSPAM@hotmail.com> wrote:
>> Perhaps this is better :
>>
>> [misc.h]
>> extern ULONG somevariable;
>>
>> [misc.c]
>> ULONG somevariable = some_default_value;
>>
> Nah!

Mark's usage is correct.

> I always use "extern" *across files* (e. g. misc.c <-> main.c) but
> never between a header and a main file with the same prefix
> (misc.h<->misc.c)

I guess that you are not using extern correctly, but it is hard
to tell without details.
-- 
Ben Pfaff 
http://benpfaff.org
0
Reply blp (3953) 10/6/2009 4:58:31 PM


"Richard Heathfield" <rjh@see.sig.invalid> wrote:
>> Here's my code: (sorry 6 files)
>
> Here's something a bit better (3 files):

*grin* I hope you got the bit that it was just ONE sample function to have 
something to put the "extern" before.
Just picked the shortest I could find :-)

> /* xstring.c */
> #include "xstring.h"
> #include <ctype.h>
> void upstring(char *s)
> {
>  while(*s != '\0')
>  {
>    *s = toupper((unsigned char)*s);
>    s++;
>  }
> }

Thanks!
Seems I missed toupper() and wrote my own thing because I've never used 
ctype.h before :)
(not the most intuitive include name I can think of, rather lets me think of 
type defs  ;))

-Andreas 

0
Reply aeibach1 (47) 10/6/2009 5:03:43 PM

On  6 Oct 2009 at  6:55, Andreas Eibach wrote:
> [misc.c] inline void shortfunc(USHORT x) { ... }
> I may use
> [menu.c] extern inline void shortfunc(USHORT);
>
> However, this causes major trouble with gnu99 standard.

Unfortunately this has been a complete pig's breakfast in gcc. When
inline was standardized in C99, the usage was fundamentally incompatible
with what gcc was already doing (basically, the semantics of "inline
with no extern or static specifier" versus "extern inline" were exactly
reversed). The gcc folks really dragged their heels about changing gcc
to agree with the standard.

However, I think that since version 4.3, gcc's inline agrees with C99,
at least in -std=c99 mode. What version of gcc are you using?

0
Reply nospam59 (9762) 10/6/2009 5:20:31 PM

Andreas Eibach wrote:
> "Mark" <mark_cruzNOTFORSPAM@hotmail.com> wrote:
> > Perhaps this is better :
> >
> > [misc.h]
> > extern ULONG somevariable;
> >
> > [misc.c]
> > ULONG somevariable = some_default_value;
> >
> Nah!
>
> I always use "extern" *across files* (e. g. misc.c <-> main.c) but never
> between a header and a main file with the same prefix (misc.h<->misc.c)
> At least I never did before.

An object should be defined with external linkage only if it's going
to be used in multiple translation units. If that's the case, it
should be declared 'extern' in a single appropriate header file, and
#included into all of those translation units, to ensure that they all
are using the same declaration. In particular, misc.h should be
#included into misc.c, even though the declaration in misc.h should be
redundant with the definition in misc.c. The reason for that is to
make sure that you get an error message if the shared declaration is
actually incompatible with the definition, rather than redundant with
it.
0
Reply jameskuyper (5159) 10/6/2009 5:43:45 PM

"Andreas Eibach" <aeibach@mail.com> writes:
> "Mark" <mark_cruzNOTFORSPAM@hotmail.com> wrote:
>> Perhaps this is better :
>>
>> [misc.h]
>> extern ULONG somevariable;
>>
>> [misc.c]
>> ULONG somevariable = some_default_value;
>>
> Nah!
>
> I always use "extern" *across files* (e. g. misc.c <-> main.c) but
> never between a header and a main file with the same prefix
> (misc.h<->misc.c)
> At least I never did before.

Your C programming life is doomed to failure.

If you're not sharing a declaration between multiple .c files,
then you don't even need it to be in a header file. Turning 
the extern into a definition is precisely the wrong thing to do.

Phil
-- 
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1
0
Reply thefatphil_demunged (1558) 10/6/2009 6:31:53 PM


"Antoninus Twink" <nospam@nospam.invalid> wrote:
> On  6 Oct 2009 at  6:55, Andreas Eibach wrote:
>> [misc.c] inline void shortfunc(USHORT x) { ... }
>> I may use
>> [menu.c] extern inline void shortfunc(USHORT);
>>
>> However, this causes major trouble with gnu99 standard.
>
> Unfortunately this has been a complete pig's breakfast in gcc. When
> inline was standardized in C99, the usage was fundamentally incompatible
> with what gcc was already doing

You can bet your life on it that it was. Guess why I had to ask here?
Because everything I knew about it was turned by 180 degrees in the new 
standard.

> (basically, the semantics of "inline
> with no extern or static specifier" versus "extern inline" were exactly
> reversed).

Yes. I'm quite familiar with the old syntax, but the new one keeps me 
puzzled, always keeps me asking "WHY?".
"Why the hell did they create this fuss / this confusion?"

It's as if the term "wheel" would be changed to denote square objects too 
;-)

> However, I think that since version 4.3, gcc's inline agrees with C99,
> at least in -std=c99 mode. What version of gcc are you using?

minGW on Win32, v4.3.0.

-Andreas 

0
Reply aeibach1 (47) 10/6/2009 7:26:18 PM

"Phil Carmody" <thefatphil_demunged@yahoo.co.uk> wrote:
>> I always use "extern" *across files* (e. g. misc.c <-> main.c) but
>> never between a header and a main file with the same prefix
>> (misc.h<->misc.c)
>> At least I never did before.
>
> Your C programming life is doomed to failure.

Don't shoot too quick, will you?
There is always a possibility that you misunderstood something I said.

> If you're not sharing a declaration between multiple .c files,

But I do! Very often even.
*Sigh* Sometimes I have a feeling I'm talking Chinese...

> then you don't even need it to be in a header file. Turning
> the extern into a definition is precisely the wrong thing to do.

I normally had it this way: (but with functions; rarely with variables, 
though)
(obvious that I #include the .h into the c, I omitted this bit)

[misc.h]
ULONG myfunc(void);  /*original */

[main.h]
extern ULONG myfunc(void);  /*so i can access myfunc() from within main.c 
*/

and optionally, if I need it elsewhere too:

[menu.h]
extern ULONG myfunc(void);  /*so i can access myfunc() from within menu.c 
too  */

Anything wrong with that?!
I doubt it.

-Andreas  
0
Reply aeibach1 (47) 10/6/2009 7:30:07 PM

On 2009-10-06, Andreas Eibach <aeibach@mail.com> wrote:
> Yes. I'm quite familiar with the old syntax, but the new one keeps me 
> puzzled, always keeps me asking "WHY?".
> "Why the hell did they create this fuss / this confusion?"

Long story short, back in the day, there was not good rapport between the
gcc and ISO C communities.  There were no gcc people involved in the standards
work, so their existing practice was somewhat underrepresented.

-s
-- 
Copyright 2009, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
0
Reply usenet-nospam (2199) 10/6/2009 7:37:20 PM

Andreas Eibach wrote:
> [...]
> I normally had it this way: (but with functions; rarely with variables, 
> though)
> (obvious that I #include the .h into the c, I omitted this bit)
> 
> [misc.h]
> ULONG myfunc(void);  /*original */
> 
> [main.h]
> extern ULONG myfunc(void);  /*so i can access myfunc() from within 
> main.c */
> 
> and optionally, if I need it elsewhere too:
> 
> [menu.h]
> extern ULONG myfunc(void);  /*so i can access myfunc() from within 
> menu.c too  */
> 
> Anything wrong with that?!
> I doubt it.

     Not "wrong," but not "good" either.  You are declaring
the same thing (myfunc) in three different places, and defining
it in yet a fourth, which gives you lots of opportunities to
make a mistake and have the declarations disagree with each
other (and hence to have at least one of them disagree with
the definition).  A comment like

	/* make sure this agrees with misc.h and main.h */
	extern ULONG myfunc(void);

gives at best an illusion of safety.

     It is usually better to declare a function or variable or
type in just one header, and #include that unique header wherever
the declaration is needed, than to scatter multiple declarations
over several headers.  Sometimes the circumstances compel you to
the duplicated-declaration approach (consider the many Standard
headers that define size_t, for example), but I'd suggest you
avoid it except as a last resort.

-- 
Eric Sosman
esosman@ieee-dot-org.invalid
0
Reply esosman2 (2945) 10/6/2009 8:09:35 PM

Andreas Eibach wrote:
> "Phil Carmody" <thefatphil_demunged@yahoo.co.uk> wrote:
> >> I always use "extern" *across files* (e. g. misc.c <-> main.c) but
> >> never between a header and a main file with the same prefix
> >> (misc.h<->misc.c)
> >> At least I never did before.
....
> I normally had it this way: (but with functions; rarely with variables,
> though)
> (obvious that I #include the .h into the c, I omitted this bit)
>
> [misc.h]
> ULONG myfunc(void);  /*original */
>
> [main.h]
> extern ULONG myfunc(void);  /*so i can access myfunc() from within main.c
> */
>
> and optionally, if I need it elsewhere too:
>
> [menu.h]
> extern ULONG myfunc(void);  /*so i can access myfunc() from within menu.c
> too  */
>
> Anything wrong with that?!

Yes - you're declaring the same function in three different places
(you're also declaring it in the definition of of the function, but
that's unavoidable, and a different issue). When you have only a small
body of code, the disadvantages of having multiple declarations are
not obvious, but they get to be pretty severe once you've written a
sufficiently large body of code. They all have to match, or the ways
in which your program can malfunction can get pretty bizarre, and
debugging the problem gets very difficult. Once you've got them all
matching, if you ever change one of them, you'll need to change all of
them, for the same reason. This can become a maintenance nightmare.

Everything should be declared in exactly one place; if the declaration
is needed in more than one translation unit (TU), than the place it's
declared in should be a header file, that is shared in all of the TUs
where the declaration is needed, by using #include. It should also be
#included in one TU where it is technically not needed: the place
where the thing is defined - the purpose of this is to ensure that the
definition is compatiple with the header file declaration.

Second issue: the 'extern' on the function declaration is unnecessary:
"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)

A third problem is that the appropriate way to handle this is
different for objects than for functions. For objects with external
linkage, the extern is absolutely necessary.

The reason for this difference is that a function declaration without
a function body always declares a function defined somewhere else. In
contrast, an uninitialized file-scope object declaration that uses
neither the 'static' nor the 'extern' keyword, is considered a
tentative definition. In general, such a tentative definition
automatically becomes an external definition of an zero-initialized
object (6.9.2p2). If you don't use an 'extern' in your header file
declaration, you could have a separate external definitions of the
object in each translation unit - the behaviour of such a program is
undefined.

Can you avoid this problem by preventing the automatic conversion? No.
There's several possible ways to interfere with that conversion, none
of which are good in this context:

a) A prior 'static' file scope declaration of the identifier would
give it internal linkage - which is generally not what you want to
have happen to a declaration you bothered putting in a header file.

b) A following 'static' declaration would make the behaviour undefined
(6.6.2p7), which doesn't do much good, either.

c) A prior or following file scope declaration of the identifier with
an initializer will make it use that initializer, rather than the
default value of 0. This doesn't help avoid the multiple external
definitions problem.
0
Reply jameskuyper (5159) 10/6/2009 8:51:09 PM

"Andreas Eibach" <aeibach@mail.com> writes:
> "Phil Carmody" <thefatphil_demunged@yahoo.co.uk> wrote:
>>> I always use "extern" *across files* (e. g. misc.c <-> main.c) but
>>> never between a header and a main file with the same prefix
>>> (misc.h<->misc.c)
>>> At least I never did before.
>>
>> Your C programming life is doomed to failure.
>
> Don't shoot too quick, will you?
> There is always a possibility that you misunderstood something I said.
>
>> If you're not sharing a declaration between multiple .c files,
>
> But I do! Very often even.
> *Sigh* Sometimes I have a feeling I'm talking Chinese...

If you are not using the same terminology as the standard and the
rest of us here, then what you say might be indistinguishable from 
Chinese.

>> then you don't even need it to be in a header file. Turning
>> the extern into a definition is precisely the wrong thing to do.
>
> I normally had it this way: (but with functions; rarely with
> variables, though)

Variables and functions behave differently in this respect.

> (obvious that I #include the .h into the c, I omitted this bit)
>
> [misc.h]
> ULONG myfunc(void);  /*original */
>
> [main.h]
> extern ULONG myfunc(void);  /*so i can access myfunc() from within
> main.c */
>
> and optionally, if I need it elsewhere too:
>
> [menu.h]
> extern ULONG myfunc(void);  /*so i can access myfunc() from within
> menu.c too  */
>
> Anything wrong with that?!

Plenty, style-wise, and source-code-management-wise. If you change 
myfunc to take a parameter in menu.? but forget to change the other 
occurences, then you've got untruths in {misc,main}.h. Untruths 
which can lead to undefined behaviour. Never duplicate anything 
which can't as easily be done in one place.

> I doubt it.

How deeply is your head buried in the sand?

You have a lot to learn, and unless you demonstrate an attitude showing
a willingness to learn, it's certainly not going to be me who will 
waste effort helping you.

Phil
-- 
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1
0
Reply thefatphil_demunged (1558) 10/6/2009 9:02:58 PM

Seebs <usenet-nospam@seebs.net> writes:
> On 2009-10-06, Andreas Eibach <aeibach@mail.com> wrote:
>> Yes. I'm quite familiar with the old syntax, but the new one keeps me 
>> puzzled, always keeps me asking "WHY?".
>> "Why the hell did they create this fuss / this confusion?"
>
> Long story short, back in the day, there was not good rapport between the
> gcc and ISO C communities.  There were no gcc people involved in the standards
> work, so their existing practice was somewhat underrepresented.

I don't think that's the issue, really. I think the problem is that
gcc forged on ahead with their extension, and when the stds committee
noticed there was a use for the feature, they thought about it, used
a little bit of grey matter, and realised that gcc had implemented 
it in *completely* the wrong way. 

Lack of dialogue perhaps made the WG think "surely they can't be so 
braindead as to implement it with completely unintuitive semantics?!",
but I like to think they'd never have been crazy enough to adopt the
same mistake just because of precedence.

Phil
-- 
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1
0
Reply thefatphil_demunged (1558) 10/6/2009 9:08:28 PM

Andreas Eibach wrote:
> 
> 
> "Mark" <mark_cruzNOTFORSPAM@hotmail.com> wrote:
>> Perhaps this is better :
>>
>> [misc.h]
>> extern ULONG somevariable;
>>
>> [misc.c]
>> ULONG somevariable = some_default_value;
>>
> Nah!
> 
> I always use "extern" *across files* (e. g. misc.c <-> main.c) but never 
> between a header and a main file with the same prefix (misc.h<->misc.c)
> At least I never did before.

Then presumably you never needed to include a header in another C file. 
If you did, you'd find your linker complaining about two definitions of 
somevariable
0
Reply markmcintyre2 (407) 10/6/2009 10:56:07 PM

Andreas Eibach wrote:
> 
> I normally had it this way: (but with functions; rarely with variables, 
> though)
> (obvious that I #include the .h into the c, I omitted this bit)
> 
> [misc.h]
> ULONG myfunc(void);  /*original */
> 
> [main.h]
> extern ULONG myfunc(void);  /*so i can access myfunc() from within 
> main.c */
> 
> and optionally, if I need it elsewhere too:
> 
> [menu.h]
> extern ULONG myfunc(void);  /*so i can access myfunc() from within 
> menu.c too  */
> 
> Anything wrong with that?!
> I doubt it.

You have the same thing typed three times, twice in headers which aren't 
even related to myfunc(). That's bad. One day you will change  myfunc() 
and forget to update the other references to it with odd results. At 
best, you will need to edit many files to update the definitions. 
Imagine a very large project with dozens, perhaps hundreds of C files - 
all requiring myfunc()....

You should have a single declaration visible to all C files via a shared 
header, and a single definition in just one of the C files.






> -Andreas 


-- 
Mark McIntyre

CLC FAQ <http://c-faq.com/>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>
0
Reply markmcintyre2 (407) 10/6/2009 11:00:59 PM


"Phil Carmody" <thefatphil_demunged@yahoo.co.uk> wrote:
>>> Your C programming life is doomed to failure.

> If you are not using the same terminology as the standard and the
> rest of us here, then what you say might be indistinguishable from
> Chinese.

> How deeply is your head buried in the sand?

Deeply enough so I can't hear you anymore ;-)

> You have a lot to learn, and unless you demonstrate an attitude showing
> a willingness to learn, it's certainly not going to be me who will
> waste effort helping you.

Um, I can easily do without, trust me.
So if you want to stop "wasting effort", you may as well do it right now!
Frankly, I don't like your tone too much, it sounds like "everyone needs to 
program the way that I do, because otherwise this will be 'doomed to 
failure'".
Same goes for generalizing statements like "...doomed to failure".

-Andreas 

0
Reply aeibach1 (47) 10/7/2009 1:24:34 AM


"Seebs" <usenet-nospam@seebs.net> wrote:
> On 2009-10-06, Andreas Eibach <aeibach@mail.com> wrote:
>> Yes. I'm quite familiar with the old syntax, but the new one keeps me
>> puzzled, always keeps me asking "WHY?".
>> "Why the hell did they create this fuss / this confusion?"
>
> Long story short, back in the day, there was not good rapport between the
> gcc and ISO C communities.  There were no gcc people involved in the 
> standards
> work, so their existing practice was somewhat underrepresented.

Heh. Interesting insights, didn't know that. Thanks. :)

-Andreas 

0
Reply aeibach1 (47) 10/7/2009 1:25:55 AM



"Phil Carmody" <thefatphil_demunged@yahoo.co.uk> wrote:
>>> Your C programming life is doomed to failure.

> If you are not using the same terminology as the standard and the
> rest of us here, then what you say might be indistinguishable from
> Chinese.

> How deeply is your head buried in the sand?

Deeply enough so I can't hear you anymore I guess ;-)

> You have a lot to learn, and unless you demonstrate an attitude showing
> a willingness to learn, it's certainly not going to be me who will
> waste effort helping you.

Um, I can easily do without, trust me.
So if you want to stop "wasting effort", you may as well do it right now!
Frankly, I don't like your tone too much, it sounds like "everyone needs to
program the way that I do, because otherwise this will be 'doomed to
failure'".

-Andreas 

0
Reply aeibach1 (47) 10/7/2009 1:27:41 AM


"Eric Sosman" <esosman@ieee-dot-org.invalid> wrote:
>     It is usually better to declare a function or variable or
> type in just one header, and #include that unique header wherever
> the declaration is needed, than to scatter multiple declarations
> over several headers.

So you're basically saying: do without 'extern' completely?
(at least for functions)

Actually it seems to me that I'm rather attracting multiple definition 
errors *BY* #including one and the same foo.h in different TUs!
Supposed myfunc() is needed in each of x.h, y.h and z.h:

[foo.h]
ULONG myfunc();

[x.h]
#include "foo.h"
[y.h]
#include "foo.h"
[z.h]
#include "foo.h"

That's what you had in mind, right?
Looks horribly redundant to me, at first sight...
Since I'm pretty accurate with my 'extern' declarations, I haven't run into 
any trouble yet.
For me this is no lesser "awkward", to say the least...but ymmv

-Andreas 

0
Reply aeibach1 (47) 10/7/2009 1:43:14 AM

Andreas Eibach wrote:
> 
> 
> "Eric Sosman" <esosman@ieee-dot-org.invalid> wrote:
>>     It is usually better to declare a function or variable or
>> type in just one header, and #include that unique header wherever
>> the declaration is needed, than to scatter multiple declarations
>> over several headers.
> 
> So you're basically saying: do without 'extern' completely?
> (at least for functions)

"extern" is pointless for functions, and absolutely essential when 
declaring objects.

> Actually it seems to me that I'm rather attracting multiple definition 
> errors *BY* #including one and the same foo.h in different TUs!

That would be a danger only if your foo.h contains definitions; it 
should only contain declarations, not definitions. Make sure that your 
header files do not provide bodies for the functions they declare. Make 
sure that any objects declared in a header  use 'extern', and are not 
initialized. That's all you need to do to avoid this problem.

0
Reply jameskuyper (5159) 10/7/2009 1:47:18 AM

"Andreas Eibach" <aeibach@mail.com> writes:
> "Eric Sosman" <esosman@ieee-dot-org.invalid> wrote:
>>     It is usually better to declare a function or variable or
>> type in just one header, and #include that unique header wherever
>> the declaration is needed, than to scatter multiple declarations
>> over several headers.
>
> So you're basically saying: do without 'extern' completely?
> (at least for functions)
>
> Actually it seems to me that I'm rather attracting multiple definition
> errors *BY* #including one and the same foo.h in different TUs!
> Supposed myfunc() is needed in each of x.h, y.h and z.h:
>
> [foo.h]
> ULONG myfunc();
>
> [x.h]
> #include "foo.h"
> [y.h]
> #include "foo.h"
> [z.h]
> #include "foo.h"
>
> That's what you had in mind, right?

No, you're missing the include guard in foo.h:

[foo.h]
#ifndef H_FOO
#define H_FOO
ULONG myfunc();
#endif /* H_FOO */

[x.h]
#ifndef H_X
#define H_X
#include "foo.h"
#endif /* H_X */

[y.h]
#ifndef H_Y
#define H_Y
#include "foo.h"
#endif /* H_Y */

[z.h]
#ifndef H_Z
#define H_Z
#include "foo.h"
#endif /* H_Z */

This guarantees that each header's contents will be included only once
in each translation unit.

(It would be more natural to use "FOO_H" as the include guard
name for "foo.h"; the problem is that identifiers starting with
'E' are reserved for errno constants, so something like "EDIT_H"
could conceivably create a conflict.)

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21473) 10/7/2009 1:57:15 AM

James Kuyper <jameskuyper@verizon.net> writes:
[...]
>> Actually it seems to me that I'm rather attracting multiple
>> definition errors *BY* #including one and the same foo.h in
>> different TUs!
>
> That would be a danger only if your foo.h contains definitions; it
> should only contain declarations, not definitions. Make sure that your
> header files do not provide bodies for the functions they
> declare. Make sure that any objects declared in a header  use
> 'extern', and are not initialized. That's all you need to do to avoid
> this problem.

In my followup, I missed the "in different TUs" part.

Including the same header in multiple translation units is not
a problem.  Including it multiple times in a single translation
unit can cause problems; these problems can be avoided by the use
of include guards.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21473) 10/7/2009 2:07:09 AM


"Mark McIntyre" <markmcintyre@TROUSERSspamcop.net> wrote:
> Andreas Eibach wrote:
>>
>>
>> "Mark" <mark_cruzNOTFORSPAM@hotmail.com> wrote:
>>> Perhaps this is better :
>>>
>>> [misc.h]
>>> extern ULONG somevariable;
>>>
>>> [misc.c]
>>> ULONG somevariable = some_default_value;
>>>
>> Nah!
>>
>> I always use "extern" *across files* (e. g. misc.c <-> main.c) but never
>> between a header and a main file with the same prefix (misc.h<->misc.c)
>> At least I never did before.
>
> Then presumably you never needed to include a header in another C file. If
> you did, you'd find your linker complaining about two definitions of
> somevariable

But I did need that. And lo' and behold, I've also run across the multiple
definition problem many times :)
That's why one needs that #ifdef BLAH_H / #define BLAH_H / #endif
preprocessor guff (almost every time).

In a nutshell:
I'd use "extern" for "misc.h" <-> "main.h", "menu.h" <-> "main.h" and the
rest of those combinations...
but NOT:

main.h<->main.c, menu.h <->menu.c and so on.
You get me? That's what I meant by "same prefix".

-Andreas 

0
Reply aeibach1 (47) 10/7/2009 2:14:18 AM

On 7 Oct, 02:24, "Andreas Eibach" <aeib...@mail.com> wrote:
> "Phil Carmody" <thefatphil_demun...@yahoo.co.uk> wrote:

> >>> Your C programming life is doomed to failure.
>
> > If you are not using the same terminology as the standard and the
> > rest of us here, then what you say might be indistinguishable from
> > Chinese.
> > How deeply is your head buried in the sand?
>
> Deeply enough so I can't hear you anymore ;-)

your loss


> > You have a lot to learn, and unless you demonstrate an attitude showing
> > a willingness to learn, it's certainly not going to be me who will
> > waste effort helping you.
>
> Um, I can easily do without, trust me.
> So if you want to stop "wasting effort", you may as well do it right now!
> Frankly, I don't like your tone too much, it sounds like "everyone needs to
> program the way that I do, because otherwise this will be 'doomed to
> failure'".

do you apply the same reasoning to everyone else that is correcting
your misconceptions?

Some things in programming are matters of opinion

   if (x == 0) z = -1;

or

   if (0 == x)
   {
       z = -1;
   }

Others are simply mistakes. Your practice of putting the same text
in different files is error prone. The database people call this
Normal Form. If you store the same information in multiple places
then it *will* go out of sync.

I have access to the source of a project and one header file is
included in
4762 other files. Would you really want to inline that file and have
to maintain
4762 different files? This is admittedly a rather extreme example!


> Same goes for generalizing statements like "...doomed to failure".

certain practices, how does it go (from memory):-

"some practices invite errors whilst this practice dials an 0800
number
 and orders errors to be delivered directly to your door"

0
Reply nick_keighley_nospam (4574) 10/7/2009 10:21:59 AM

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Keith Thompson wrote:

> James Kuyper <jameskuyper@verizon.net> writes:
> [...]
>>> Actually it seems to me that I'm rather attracting multiple
>>> definition errors *BY* #including one and the same foo.h in
>>> different TUs!
>>
>> That would be a danger only if your foo.h contains definitions; it
>> should only contain declarations, not definitions. Make sure that your
>> header files do not provide bodies for the functions they
>> declare. Make sure that any objects declared in a header  use
>> 'extern', and are not initialized. That's all you need to do to avoid
>> this problem.
> 
> In my followup, I missed the "in different TUs" part.
> 
> Including the same header in multiple translation units is not
> a problem.  Including it multiple times in a single translation
> unit can cause problems; these problems can be avoided by the use
> of include guards.
> 

How about putting a templated function definition inside the header? 
Example:

#ifndef _foo_hpp
# define _foo_hpp
template<class t>void swap(t&a,t&b){
	t c=a;
	a=b;
	b=c;
}
#endif

In this case, using swap<int> in 2 different TUs will cause a linker 
conflict. However, putting the definition in foo.c will cause undefined 
references.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAkrMbAsACgkQG6NzcAXitM8DiACfeakv2YsDh8NNMBfIahNQwqwT
nl0Amwb3Inev+k1c1cKQRWq9fVlNNvtM
=p93I
-----END PGP SIGNATURE-----

0
Reply miklcct (62) 10/7/2009 10:23:07 AM

Michael Tsang wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Keith Thompson wrote:
> 
>> James Kuyper <jameskuyper@verizon.net> writes:
>> [...]
>>>> Actually it seems to me that I'm rather attracting multiple
>>>> definition errors *BY* #including one and the same foo.h in
>>>> different TUs!
>>> That would be a danger only if your foo.h contains definitions; it
>>> should only contain declarations, not definitions. Make sure that your
>>> header files do not provide bodies for the functions they
>>> declare. Make sure that any objects declared in a header  use
>>> 'extern', and are not initialized. That's all you need to do to avoid
>>> this problem.
>> In my followup, I missed the "in different TUs" part.
>>
>> Including the same header in multiple translation units is not
>> a problem.  Including it multiple times in a single translation
>> unit can cause problems; these problems can be avoided by the use
>> of include guards.
>>
> 
> How about putting a templated function definition inside the header? 

This is comp.lang.c; you're thinking of That Other Language.
0
Reply jameskuyper (5159) 10/7/2009 10:36:19 AM

Andreas Eibach wrote:
> 
> 
> "Eric Sosman" <esosman@ieee-dot-org.invalid> wrote:
>>     It is usually better to declare a function or variable or
>> type in just one header, and #include that unique header wherever
>> the declaration is needed, than to scatter multiple declarations
>> over several headers.
> 
> So you're basically saying: do without 'extern' completely?
> (at least for functions)

     You don't need `extern' on a function declaration, but it's
harmless.  It may also help to emphasize the point that the
function itself isn't "here," but elsewhere.  (We habitually put
lots of unnecessary things in our source to aid readability --
white space, for example, and comments.)

> Actually it seems to me that I'm rather attracting multiple definition 
> errors *BY* #including one and the same foo.h in different TUs!
> Supposed myfunc() is needed in each of x.h, y.h and z.h:
> 
> [foo.h]
> ULONG myfunc();

     This is a declaration, but not a definition, so ...

> [x.h]
> #include "foo.h"
> [y.h]
> #include "foo.h"
> [z.h]
> #include "foo.h"

.... these are not "multiple definitions."

> That's what you had in mind, right?

     Sort of.  It's unusual for one header to #include another
merely to obtain a function declaration, because headers seldom
contain things that "use" function declarations.  An exception
would be headers containing function definitions (usually with
`inline', which is where this thread got started) which themselves
call myfunc().  More typically, one header #includes another to
acquire its macro definitions and type declarations; the function
declarations are usually of interest only to the .c files that
#include a header.

> Looks horribly redundant to me, at first sight...

     It's no more redundant that writing `ULONG myfunc();' in
four places, and it's noticeably safer.

> Since I'm pretty accurate with my 'extern' declarations, I haven't run 
> into any trouble yet.

     "Never make mistakes" is a splendid policy, but a hard one
to follow.  If you've got a team of fifty programmers working on
successive generations of a five million line program over a span
of fifteen years, you'll find that the policy becomes impossible
to follow.  That's when you find that reducing the opportunities
for making mistakes will pay off.  And even if you're only writing
toy programs of two or three thousand lines, it's just as well to
develop and practice good habits that will be helpful when you get
around to serious programming.

     The largest system I've worked on extensively grew to just
under four million lines of mixed C and Lisp, encompassing about
a hundred programs (one huge one, half a dozen large ones, and
the rest modest-sized filters and utilities of various kinds).
This is by no means a "huge" system as such things go, but we
could never have written, debugged, enhanced, extended, and
maintained it if we hadn't taken fullest advantage of every
mistake-avoidance trick available.  That's why I value mistake-
avoidance tricks.  (Lordy, how I wish we'd had prototypes in
those days!)

-- 
Eric Sosman
esosman@ieee-dot-org.invalid
0
Reply esosman2 (2945) 10/7/2009 1:07:12 PM

"Andreas Eibach" <aeibach@mail.com> writes:
> "Phil Carmody" <thefatphil_demunged@yahoo.co.uk> wrote:
>>>> Your C programming life is doomed to failure.
>
>> If you are not using the same terminology as the standard and the
>> rest of us here, then what you say might be indistinguishable from
>> Chinese.
>
>> How deeply is your head buried in the sand?
>
> Deeply enough so I can't hear you anymore I guess ;-)
>
>> You have a lot to learn, and unless you demonstrate an attitude showing
>> a willingness to learn, it's certainly not going to be me who will
>> waste effort helping you.
>
> Um, I can easily do without, trust me.

That's more like head-burried-in-arse, which is even worse than 
head-burried-in-sand.

Enjoy being shit at programming. Please get a job in Microsoft,
so you can be an active part of their demise.

Phil
-- 
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1
0
Reply thefatphil_demunged (1558) 10/8/2009 7:32:38 AM

Michael Tsang <miklcct@gmail.com> writes:
> Keith Thompson wrote:
>
>> James Kuyper <jameskuyper@verizon.net> writes:
>> [...]
>>>> Actually it seems to me that I'm rather attracting multiple
>>>> definition errors *BY* #including one and the same foo.h in
>>>> different TUs!
>>>
>>> That would be a danger only if your foo.h contains definitions; it
>>> should only contain declarations, not definitions. Make sure that your
>>> header files do not provide bodies for the functions they
>>> declare. Make sure that any objects declared in a header  use
>>> 'extern', and are not initialized. That's all you need to do to avoid
>>> this problem.
>> 
>> In my followup, I missed the "in different TUs" part.
>> 
>> Including the same header in multiple translation units is not
>> a problem.  Including it multiple times in a single translation
>> unit can cause problems; these problems can be avoided by the use
>> of include guards.
>> 
>
> How about putting a templated function definition inside the header? 

There's no such thing.

> Example:
>
> #ifndef _foo_hpp
> # define _foo_hpp
> template<class t>void swap(t&a,t&b){

That's not C. Please evolve a brain.

Phil
-- 
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1
0
Reply thefatphil_demunged (1558) 10/8/2009 7:34:08 AM

Phil Carmody <thefatphil_demunged@yahoo.co.uk> writes:

> "Andreas Eibach" <aeibach@mail.com> writes:
>> "Phil Carmody" <thefatphil_demunged@yahoo.co.uk> wrote:
>>>>> Your C programming life is doomed to failure.
>>
>>> If you are not using the same terminology as the standard and the
>>> rest of us here, then what you say might be indistinguishable from
>>> Chinese.
>>
>>> How deeply is your head buried in the sand?
>>
>> Deeply enough so I can't hear you anymore I guess ;-)
>>
>>> You have a lot to learn, and unless you demonstrate an attitude showing
>>> a willingness to learn, it's certainly not going to be me who will
>>> waste effort helping you.
>>
>> Um, I can easily do without, trust me.
>
> That's more like head-burried-in-arse, which is even worse than 
> head-burried-in-sand.
>
> Enjoy being shit at programming. Please get a job in Microsoft,
> so you can be an active part of their demise.
>
> Phil

Why are you so keen on promoting yourself as another obnoxiuous c.l.c
shit?

-- 
"Avoid hyperbole at all costs, its the most destructive argument on
the planet" - Mark McIntyre in comp.lang.c
0
Reply rgrdev_ (1087) 10/8/2009 7:57:47 AM

On 7 Oct, 02:43, "Andreas Eibach" <aeib...@mail.com> wrote:
> "Eric Sosman" <esos...@ieee-dot-org.invalid> wrote:

> > =A0 =A0 It is usually better to declare a function or variable or
> > type in just one header, and #include that unique header wherever
> > the declaration is needed, than to scatter multiple declarations
> > over several headers.
>
> So you're basically saying: do without 'extern' completely?
> (at least for functions)

rather, "do without extern for functions, you must use it for
objects (data)". I know that logically says the same thing but
the emphasis is odd in your version. You *must* use extern
for objects in header files.

> Actually it seems to me that I'm rather attracting multiple definition
> errors *BY* #including one and the same foo.h in different TUs!

you are still confused between "declaration" and "definition". (It
took me *years* to sort out- I think C has it backwards). You won't
have multiple definition problems by including header files. Because
A HEADER FILE WON'T HAVE ANY DEFINIONS IN IT!!

int pippo (int x);

isn't a definition it's a declaration.


> Supposed myfunc() is needed in each of x.h, y.h and z.h:
>
> [foo.h]
> ULONG myfunc();

this isn't a proper prototype. You want
ULONG myfunc(void);

(putting nothing in the brackets *in a declaration* means "takes an
unknown
number of arguments").


> [x.h]
> #include "foo.h"
> [y.h]
> #include "foo.h"
> [z.h]
> #include "foo.h"
>
> That's what you had in mind, right?
> Looks horribly redundant to me, at first sight...

how come? If all of x,y and z use myfunc() what simpler
method is there of getting the correct prototype (declaration)
than pulling the right header in?

> Since I'm pretty accurate with my 'extern' declarations,

pretty accurate...


> I haven't run into
> any trouble yet.
> For me this is no lesser "awkward", to say the least...but ymmv

it never seems awkward to me


0
Reply nick_keighley_nospam (4574) 10/8/2009 8:08:00 AM


"Nick Keighley" <nick_keighley_nospam@hotmail.com> wrote:
>> So you're basically saying: do without 'extern' completely?
>> (at least for functions)
>
> rather, "do without extern for functions, you must use it for
> objects (data)". I know that logically says the same thing but
> the emphasis is odd in your version. You *must* use extern
> for objects in header files.

Hi again,

well I never do without reading along information *while* posting here, so 
at least I have to admit that the use of extern in functions IS rare.
That's a fact.
And yes too to the fact that the uses in func's and in var's are really 
apples & oranges.
Frankly, I had no idea that there is *THAT* much diversity...

> you are still confused between "declaration" and "definition". (It
> took me *years* to sort out- I think C has it backwards).

> have multiple definition problems by including header files. Because
> A HEADER FILE WON'T HAVE ANY DEFINIONS IN IT!!

Yes *bangs head* I meant multiple *declaration* problems.

> int pippo (int x);
>
> isn't a definition it's a declaration.
>
>
>> Supposed myfunc() is needed in each of x.h, y.h and z.h:
>>
>> [foo.h]
>> ULONG myfunc();
>
> this isn't a proper prototype. You want
> ULONG myfunc(void);

True. Lazy typist. (/me)
In code, I normally set them. But don't forget, at highest warning level, I 
would have warnings there :-)
Unfortunately not here, so when "writing code in the wild" and without a 
compiler at hand, this happens :-)

-Andreas 

0
Reply aeibach1 (47) 10/8/2009 7:58:49 PM


"James Kuyper" <jameskuyper@verizon.net> wrote:
>> So you're basically saying: do without 'extern' completely?
>> (at least for functions)
>
> "extern" is pointless for functions, and absolutely essential when 
> declaring objects.

extern in functions and extern in objects are in fact two different pairs of 
socks.
Meanwhile, I've (re-)read several sections about this matter.

>> Actually it seems to me that I'm rather attracting multiple definition 
>> errors *BY* #including one and the same foo.h in different TUs!
>
> That would be a danger only if your foo.h contains definitions; it should 
> only contain declarations, not definitions.

"Should" yes. But what if they do anyway?
(Since this could bring us easily back to the actual topic: inlines. =))
Since inline functions are often found to be both declared *and* defined in 
header files, this WILL call for trouble then, won't it?
So it will require anyone using those inlines to think about a strategy how 
to avoid ugly errors.

That's another reason why I thought about using the extern (for functions) 
way, just *to* avoid this problem.

-Andreas 

0
Reply aeibach1 (47) 10/8/2009 8:05:14 PM

Andreas Eibach wrote:
> "Nick Keighley" <nick_keighley_nospam@hotmail.com> wrote:
....
> > you are still confused between "declaration" and "definition". (It
> > took me *years* to sort out- I think C has it backwards).
>
> > have multiple definition problems by including header files. Because
> > A HEADER FILE WON'T HAVE ANY DEFINIONS IN IT!!
>
> Yes *bangs head* I meant multiple *declaration* problems.

The point is, multiple definitions would be a problem; but multiple
declarations are not; not so long as they're identical.
0
Reply jameskuyper (5159) 10/8/2009 8:09:03 PM

Nick Keighley <nick_keighley_nospam@hotmail.com> wrote:

> On 7 Oct, 02:43, "Andreas Eibach" <aeib...@mail.com> wrote:

> > Actually it seems to me that I'm rather attracting multiple definition
> > errors *BY* #including one and the same foo.h in different TUs!
> 
> you are still confused between "declaration" and "definition". (It
> took me *years* to sort out- I think C has it backwards).

Not IMO. To declare is to state _that_ something is, whereas to define
is to state _what_ it is. When Oscar Wilde had nothing to declare except
his genius, he certainly didn't expect to have to explain exactly why
"Earnest" is so hilarious (which was just as well, since, given that it
would have been New York Customs House officers trying to understand the
humour, it would have been completely in vain).

And that's precisely how C has it.

Richard
0
Reply raltbos (821) 10/8/2009 8:35:56 PM

Andreas Eibach wrote:
> "James Kuyper" <jameskuyper@verizon.net> wrote:
> >> So you're basically saying: do without 'extern' completely?
> >> (at least for functions)
> >
> > "extern" is pointless for functions, and absolutely essential when
> > declaring objects.
>
> extern in functions and extern in objects are in fact two different pairs of
> socks.
> Meanwhile, I've (re-)read several sections about this matter.
>
> >> Actually it seems to me that I'm rather attracting multiple definition
> >> errors *BY* #including one and the same foo.h in different TUs!
> >
> > That would be a danger only if your foo.h contains definitions; it should
> > only contain declarations, not definitions.
>
> "Should" yes. But what if they do anyway?

Headers that contain external definitions are always a design error.
Headers are supposed to be used to share code between multiple
translation units (TUs); if something is not intended to be shared, it
should be defined in the main program files, not the header. If it's
meant to be shared, it will appear in multiple TUs, and for external
definitions that would mean that the behaviour would be undefined.

Headers that define functions or objects with internal linkage define
a separate function or object with the same name in each translation
unit they are #included into. There's rare but legitimate reasons for
doing so, mostly involving inline functions, as you pointed out.

> (Since this could bring us easily back to the actual topic: inlines. =))
> Since inline functions are often found to be both declared *and* defined in
> header files, this WILL call for trouble then, won't it?

There are three possibilities:

The inline functions functions are declared 'static': no problem, the
functions have internal linkage.

The inline functions have implicit external linkage: no problem. The
key point is that the function definition in the header becomes an
inline definition, which is NOT an external definition (6.7.4p6).
However, when this is the case, you must make sure that one (and only
one!) translation unit also has an external definition for the
function, because each time such a function is called, the
implementation is free to decide whether to use the inline definition
from the header file, or the external definition provided elsewhere.
That's what went wrong with your code. You provided an inline
defintion, and you declared an external definition, but nowhere in
your code did you actually define an external definition.

The inline functions are explicitly declared 'extern'. Big problem, if
this occurs in more than one translation unit. Therefore, this should
NEVER be done in a header, because the mail point of having a header
file is to put it into multiple translation units.

> So it will require anyone using those inlines to think about a strategy how
> to avoid ugly errors.
>
> That's another reason why I thought about using the extern (for functions)
> way, just *to* avoid this problem.

As you see above, putting 'extern' on an inline function declaration
in a header file CAUSES the very problem you're trying to avoid.
0
Reply jameskuyper (5159) 10/8/2009 9:55:53 PM

"jameskuyper" <jameskuyper@verizon.net> wrote:
> Andreas Eibach wrote:
>> (Since this could bring us easily back to the actual topic: inlines. =))
>> Since inline functions are often found to be both declared *and* defined 
>> in
>> header files, this WILL call for trouble then, won't it?
>
> There are three possibilities:
>
> The inline functions functions are declared 'static': no problem, the
> functions have internal linkage.

Yes, but IMHO this would not solve my problem, because then I may only use 
the inline function in *one* TU.
(Unless I'm thinking the wrong way here)

> The inline functions have implicit external linkage: no problem. The
> key point is that the function definition in the header becomes an
> inline definition, which is NOT an external definition (6.7.4p6).

Heck yeah. _That_ was the tricky bit to remember. Thanks for refreshing my 
memory again...

> However, when this is the case, you must make sure that one (and only
> one!) translation unit also has an external definition for the
> function, because each time such a function is called, the
> implementation is free to decide whether to use the inline definition
> from the header file, or the external definition provided elsewhere.
> That's what went wrong with your code. You provided an inline
> defintion, and you declared an external definition, but nowhere in
> your code did you actually define an external definition.

Yeah. That might be it.
So this should look like this:

(TU#1)
inline void blah(int x) {/* code */ }

*AND*
(TU#2)
extern inline void blah(int x);

*AND*
(TU#3)
extern inline void blah(int x) {/* code */ }

aw'ite?

The tricky bit is having the /* code */ TWICE.
Outside this special case, you'd fear a duplicate definition error.
But this automagical transition of the linkage class (6.7.4p6) turns things 
vice-versa, of course.

> The inline functions are explicitly declared 'extern'. Big problem, if
> this occurs in more than one translation unit. Therefore, this should
> NEVER be done in a header, because the mail point of having a header
> file is to put it into multiple translation units.

ACK.

> As you see above, putting 'extern' on an inline function declaration
> in a header file CAUSES the very problem you're trying to avoid.

Yeah, I even knew that before that it's due to a dupe problem. Just needed 
to know which exactly :)

Thanks for one of the most insightful posts ever in this discussion.

-Andreas

 

0
Reply aeibach1 (47) 10/9/2009 1:23:52 AM

Andreas Eibach wrote:
> 
> "jameskuyper" <jameskuyper@verizon.net> wrote:
....
>> There are three possibilities:
>>
>> The inline functions functions are declared 'static': no problem, the
>> functions have internal linkage.
> 
> Yes, but IMHO this would not solve my problem, because then I may only 
> use the inline function in *one* TU.
> (Unless I'm thinking the wrong way here)

You probably are. You can use the inline function in every TU where you 
#include the appropriate header.

....
>> However, when this is the case, you must make sure that one (and only
>> one!) translation unit also has an external definition for the
>> function, because each time such a function is called, the
>> implementation is free to decide whether to use the inline definition
>> from the header file, or the external definition provided elsewhere.
>> That's what went wrong with your code. You provided an inline
>> defintion, and you declared an external definition, but nowhere in
>> your code did you actually define an external definition.
> 
> Yeah. That might be it.
> So this should look like this:
> 
> (TU#1)
> inline void blah(int x) {/* code */ }
> 
> *AND*
> (TU#2)
> extern inline void blah(int x);

That's not permitted; if you declare an inline function, there must 
ALWAYS be a definition of it in the same translation unit; should the 
implementation choose to inline the function, that's the definition it 
will inline. That's why an inline function to be used in multiple TUs 
should be declared AND defined in a header file that is #included 
wherever needed. That's equally true whether it has internal or external 
linkage.

> *AND*
> (TU#3)
> extern inline void blah(int x) {/* code */ }
> 
> aw'ite?
> 
> The tricky bit is having the /* code */ TWICE.

You're correct about that being a problem. Here's how to avoid it. As I 
understand it (I have never actually needed to do this), the right 
approach to creating an inline function with external linkage is:

blah.h:
inline void blah(int x) {/* code */ }

blah.c:
#include "blah.h"
extern void blah(int x);
/* Note that the "extern" on this declaration causes the
  * definition in "blah.h" to become an external definition
  * rather than an inline definition. */

foo.c:
#include "blah.h"

bar.c
#include "blah.h"
0
Reply jameskuyper (5159) 10/9/2009 11:27:41 AM

On 8 Oct, 21:35, ralt...@xs4all.nl (Richard Bos) wrote:
> Nick Keighley <nick_keighley_nos...@hotmail.com> wrote:


> > you are still confused between "declaration" and "definition". (It
> > took me *years* to sort out- I think C has it backwards).
>
> Not IMO. To declare is to state _that_ something is, whereas to define
> is to state _what_ it is. When Oscar Wilde had nothing to declare except
> his genius, he certainly didn't expect to have to explain exactly why
> "Earnest" is so hilarious (which was just as well, since, given that it
> would have been New York Customs House officers trying to understand the
> humour, it would have been completely in vain).
>
> And that's precisely how C has it.


Algol-60 (and I *think* Pascal) used "declare" in the sense that
C uses "define".

I tended to think of define as saying what "shape" it was and
"declaring" actually setting aside the store. And having
said that it will take me another 5 years to sort it out again!
I have "C: one definition rule" written on the wall next to me
for exactly this reason ("oh yes, you can only have one *definition*
of something C")
0
Reply nick_keighley_nospam (4574) 10/9/2009 11:41:27 AM

46 Replies
62 Views

(page loaded in 0.386 seconds)


Reply: