<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>
<channel>
	<title>Comments on: Incomplete Types in C</title>
	<atom:link href="http://mark.santaniello.com/archives/170/feed" rel="self" type="application/rss+xml" />
	<link>http://mark.santaniello.com/archives/170</link>
	<description>the body of a very slow loop</description>
	<pubDate>Fri, 21 Nov 2008 09:09:28 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
		<item>
		<title>By: Jonathan Gilbert</title>
		<link>http://mark.santaniello.com/archives/170#comment-1859</link>
		<dc:creator>Jonathan Gilbert</dc:creator>
		<pubDate>Mon, 01 May 2006 14:37:20 +0000</pubDate>
		<guid isPermaLink="false">http://mark.santaniello.net/?p=170#comment-1859</guid>
		<description>The standard I read seems to refer to the "static" modifier as part of the symbol's linkage. Scoping refers to the namespaces affected by having that declaration at that point in that file. Thus, with or without "static", as that particular declaration affects only that file (and everywhere within that file), it is called "file scope".

The standard refers to this:

int i;

..as "external linkage", and this:

static int i;

..as "internal linkage".</description>
		<content:encoded><![CDATA[<p>The standard I read seems to refer to the &#8220;static&#8221; modifier as part of the symbol&#8217;s linkage. Scoping refers to the namespaces affected by having that declaration at that point in that file. Thus, with or without &#8220;static&#8221;, as that particular declaration affects only that file (and everywhere within that file), it is called &#8220;file scope&#8221;.</p>
<p>The standard refers to this:</p>
<p>int i;</p>
<p>..as &#8220;external linkage&#8221;, and this:</p>
<p>static int i;</p>
<p>..as &#8220;internal linkage&#8221;.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Mark</title>
		<link>http://mark.santaniello.com/archives/170#comment-1830</link>
		<dc:creator>Mark</dc:creator>
		<pubDate>Sat, 29 Apr 2006 20:18:33 +0000</pubDate>
		<guid isPermaLink="false">http://mark.santaniello.net/?p=170#comment-1830</guid>
		<description>Jonathan,

Thanks.  I've got to compare that with the official copy of the C standard that I have at work.  Also, I might bug one of the MSVC front-end guys, to get their opinion.

I'm probably playing fast-and-loose with the term "scope", but I thought file-scope in C was based on the static qualifier.

/* foo.c */
static int i; /* visible only from foo.c */

// foo.cpp
namespace {
int i;  // file-scope the C++ way
}

-Mark</description>
		<content:encoded><![CDATA[<p>Jonathan,</p>
<p>Thanks.  I&#8217;ve got to compare that with the official copy of the C standard that I have at work.  Also, I might bug one of the MSVC front-end guys, to get their opinion.</p>
<p>I&#8217;m probably playing fast-and-loose with the term &#8220;scope&#8221;, but I thought file-scope in C was based on the static qualifier.</p>
<p>/* foo.c */<br />
static int i; /* visible only from foo.c */</p>
<p>// foo.cpp<br />
namespace {<br />
int i;  // file-scope the C++ way<br />
}</p>
<p>-Mark</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jonathan Gilbert</title>
		<link>http://mark.santaniello.com/archives/170#comment-1821</link>
		<dc:creator>Jonathan Gilbert</dc:creator>
		<pubDate>Fri, 28 Apr 2006 15:38:39 +0000</pubDate>
		<guid isPermaLink="false">http://mark.santaniello.net/?p=170#comment-1821</guid>
		<description>I found a draft of some version of the C standard at the following URL:

  http://www.vmunix.com/~gabor/c/draft.html

..and while scanning through it quickly, found the following:

6.5:
       [#5]  A  declaration  specifies   the   interpretation   and
       attributes  of  a  set  of  identifiers.  A definition of an
       identifier is a declaration for that identifier that:

          - for an object, causes storage to be reserved  for  that
            object;

       [#7] If an identifier for an  object  is  declared  with  no
       linkage,  the  type  for the object shall be complete by the
       end of its declarator, or by the end of its  init-declarator
       if it has an initializer.

6.5.2.3:

       [#3] All declarations of  structure,  union,  or  enumerated
       types  that have the same scope and use the same tag declare
       the same type. The type is incomplete94  until  the  closing
       brace  of  the  list  defining  the  content,  and  complete
       thereafter.

       94. An incomplete type may only by used when the size of  an
           object  of  that  type is not needed.  It is not needed,
           for example, when a typedef name is  declared  to  be  a
           specifier for a structure or union, or when a pointer to
           or a function returning a structure or  union  is  being
           declared.   (See  incomplete  types  in  6.1.2.5.)   The
           specification shall be complete before such  a  function
           is called or defined.

From addendum K.2: Undefined behaviour

          - An identifier for an object is declared with no linkage  and
            the  type  of the object is incomplete after its declarator,
            or after its init-declarator if it has an initializer (6.5).

These would tend to suggest that Microsoft's compiler is showing compliant behaviour in rejecting the declaration of "bar" with an incomplete type. However, following up a reference not too far below the point of undefined behaviour shown above:

          - An identifier for an object with  internal  linkage  and  an
            incomplete  type  is  declared  with  a tentative definition
            (6.7.2).

.. it would seem that it is in fact valid:

6.7.2:

       [#2] A declaration of an identifier for an object  that  has
       file  scope  without  an initializer, and without a storage-
       class specifier or with the storage-class specifier  static,
       constitutes  a  tentative definition.  If a translation unit
       contains  one  or  more   tentative   definitions   for   an
       identifier,  and  the  translation unit contains no external
       definition for that identifier, then the behavior is exactly
       as if the translation unit contains a file scope declaration
       of that identifier, with the composite type as of the end of
       the translation unit, with an initializer equal to 0.

Basically, if an identifier is declared:
  * With file scope (check)
  * Without an initializer (check)
  * With no storage class specifier (check)
  * One or more times (check)
  * With no external definition within the translation unit (check)

..then the identifier's type is treated as it would be were the declaration at the very end of the file. As a bonus, it is also given an initualizer of "= {0};". So I'd have to say GCC, Intel, Comeau and anyone else who compiles the fragment you gave got it right, and Microsoft didn't read section 6.7.2 closely enough. :-)</description>
		<content:encoded><![CDATA[<p>I found a draft of some version of the C standard at the following URL:</p>
<p>  <a href="http://www.vmunix.com/~gabor/c/draft.html" rel="nofollow">http://www.vmunix.com/~gabor/c/draft.html</a></p>
<p>..and while scanning through it quickly, found the following:</p>
<p>6.5:<br />
       [#5]  A  declaration  specifies   the   interpretation   and<br />
       attributes  of  a  set  of  identifiers.  A definition of an<br />
       identifier is a declaration for that identifier that:</p>
<p>          - for an object, causes storage to be reserved  for  that<br />
            object;</p>
<p>       [#7] If an identifier for an  object  is  declared  with  no<br />
       linkage,  the  type  for the object shall be complete by the<br />
       end of its declarator, or by the end of its  init-declarator<br />
       if it has an initializer.</p>
<p>6.5.2.3:</p>
<p>       [#3] All declarations of  structure,  union,  or  enumerated<br />
       types  that have the same scope and use the same tag declare<br />
       the same type. The type is incomplete94  until  the  closing<br />
       brace  of  the  list  defining  the  content,  and  complete<br />
       thereafter.</p>
<p>       94. An incomplete type may only by used when the size of  an<br />
           object  of  that  type is not needed.  It is not needed,<br />
           for example, when a typedef name is  declared  to  be  a<br />
           specifier for a structure or union, or when a pointer to<br />
           or a function returning a structure or  union  is  being<br />
           declared.   (See  incomplete  types  in  6.1.2.5.)   The<br />
           specification shall be complete before such  a  function<br />
           is called or defined.</p>
<p>From addendum K.2: Undefined behaviour</p>
<p>          - An identifier for an object is declared with no linkage  and<br />
            the  type  of the object is incomplete after its declarator,<br />
            or after its init-declarator if it has an initializer (6.5).</p>
<p>These would tend to suggest that Microsoft&#8217;s compiler is showing compliant behaviour in rejecting the declaration of &#8220;bar&#8221; with an incomplete type. However, following up a reference not too far below the point of undefined behaviour shown above:</p>
<p>          - An identifier for an object with  internal  linkage  and  an<br />
            incomplete  type  is  declared  with  a tentative definition<br />
            (6.7.2).</p>
<p>.. it would seem that it is in fact valid:</p>
<p>6.7.2:</p>
<p>       [#2] A declaration of an identifier for an object  that  has<br />
       file  scope  without  an initializer, and without a storage-<br />
       class specifier or with the storage-class specifier  static,<br />
       constitutes  a  tentative definition.  If a translation unit<br />
       contains  one  or  more   tentative   definitions   for   an<br />
       identifier,  and  the  translation unit contains no external<br />
       definition for that identifier, then the behavior is exactly<br />
       as if the translation unit contains a file scope declaration<br />
       of that identifier, with the composite type as of the end of<br />
       the translation unit, with an initializer equal to 0.</p>
<p>Basically, if an identifier is declared:<br />
  * With file scope (check)<br />
  * Without an initializer (check)<br />
  * With no storage class specifier (check)<br />
  * One or more times (check)<br />
  * With no external definition within the translation unit (check)</p>
<p>..then the identifier&#8217;s type is treated as it would be were the declaration at the very end of the file. As a bonus, it is also given an initualizer of &#8220;= {0};&#8221;. So I&#8217;d have to say GCC, Intel, Comeau and anyone else who compiles the fragment you gave got it right, and Microsoft didn&#8217;t read section 6.7.2 closely enough. :-)</p>
]]></content:encoded>
	</item>
</channel>
</rss>
