Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Static at function prototype

58 views
Skip to first unread message

umesh.k...@gmail.com

unread,
Sep 12, 2012, 6:55:21 AM9/12/12
to
Hi All ,
Was going through the C99 standard @ http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf which states that the Function declarators as

direct-declarator ( parameter-type-list )
parameter-list: parameter-declaration
parameter-list , parameter-declaration
parameter-declaration: declaration-specifiers declarator
declaration-specifiers abstract-declarator

direct-declarator [ static type-qualifier-listopt assignment-expression ]

where The optional type qualifiers and the keyword static shall appear only in a declaration of a function parameter with an array type, and then only in the outermost
array type derivation and then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.

for example : int func(array[static int i =100) ;

I'm trying to understand that when as a programmar i can use the function prototype like above ??? Please someone can shed some lights here ??


Thanks

James Kuyper

unread,
Sep 12, 2012, 10:52:49 AM9/12/12
to
On 09/12/2012 06:55 AM, umesh.k...@gmail.com wrote:
> Hi All ,
> Was going through the C99 standard @ http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf which states that the Function declarators as

For C99, you should use n1256.pdf; that's the most complete version -
it's more complete than the official standard, by reason of including
three Technical Corrigenda.

> direct-declarator ( parameter-type-list )
> parameter-list: parameter-declaration
> parameter-list , parameter-declaration
> parameter-declaration: declaration-specifiers declarator
> declaration-specifiers abstract-declarator
>
> direct-declarator [ static type-qualifier-listopt assignment-expression ]
>
> where The optional type qualifiers and the keyword static shall appear only in a declaration of a function parameter with an array type, and then only in the outermost
> array type derivation and then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.
>
> for example : int func(array[static int i =100) ;

That declaration specifies no type for 'array'. The 'int' is not allowed
in the location where you wrote it - it's a type specifier, not a type
qualifier. In C99, type qualifiers included 'const', 'restrict', and
'volatile'; C2011 adds "_Atomic". Also, your declaration is missing a
terminating ']'.

Here's a corrected example:

int func(int array[static const i=100]);

Such a declaration is equivalent to

i=100;
int func(int * const array);

except for the impact of the 'static' keyword, which I will explain
farther down. Note that the 'const' has become the qualifier of the
'array' variable.

"... the keyword static shall appear only in a declaration of a function
parameter with an array type, and then only in the outermost array type
derivation." (6.7.6.2p1)
"If the keyword static also appears within the [ and ] of the array type
derivation, then for each call to the function, the value of the
corresponding actual argument shall provide access to the first element
of an array with at least as many elements as specified by the size
expression." (6.7.6.3p7)

Therefore, the only defined meaning for that 'static' is to leave
undefined the behavior of calling that function on a array with less
than 100 elements, behavior that would otherwise be well-defined. In
principle, this could allow optimization of the code, by allowing the
compiler to assume that the "shall" is never violated, but off-hand I
can't think of any way to take advantage of that assumption. So what
advantage does using this keyword provide?

The static keyword is intended to be used when writing a function whose
behavior would be undefined anyway, if the array were too small. For
instance, it might contain a statement like the following:

array[99] = 0;

The value of the assignment expression after the 'static' keyword
documents the minimum size of the array, and is intended to encourage
(but not require) implementors to define the behavior when the "shall"
is violated as resulting in the generation of error messages - at
compile time if possible, at run-time if necessary.

Ben Bacarisse

unread,
Sep 12, 2012, 9:33:21 PM9/12/12
to
James Kuyper <james...@verizon.net> writes:

> On 09/12/2012 06:55 AM, umesh.k...@gmail.com wrote:
<snip>
>> direct-declarator ( parameter-type-list )
>> parameter-list: parameter-declaration
>> parameter-list , parameter-declaration
>> parameter-declaration: declaration-specifiers declarator
>> declaration-specifiers abstract-declarator
>>
>> direct-declarator [ static type-qualifier-listopt assignment-expression ]
<snip>
>> for example : int func(array[static int i =100) ;
>
> That declaration specifies no type for 'array'. The 'int' is not allowed
> in the location where you wrote it - it's a type specifier, not a type
> qualifier. In C99, type qualifiers included 'const', 'restrict', and
> 'volatile'; C2011 adds "_Atomic". Also, your declaration is missing a
> terminating ']'.
>
> Here's a corrected example:
>
> int func(int array[static const i=100]);
>
> Such a declaration is equivalent to
>
> i=100;
> int func(int * const array);

I don't understand this equivalence. You seem to suggest that your
i=100 actually happens at some time just prior to the declaration, but a
non-constant expression array size at function prototype scope is
"treated as if it were replaced by *" (6.7.5.2 p5).

Incidentally, by not being a constant expression makes
array into a VLA. I suspect the OP had no intention of doing so,
i.e. the closest correction of their example is probably just:

int func(array[static 100]);

<snip>
--
Ben.

James Kuyper

unread,
Sep 13, 2012, 12:31:10 PM9/13/12
to
In C2011, that's 6.7.6.2p5. I did notice that, but didn't think about
it; I should have.

I was concentrating on the grammar for array declarations, which says:

D[ static type-qualifier-listopt assignment-expression ]
D[ type-qualifier-list static assignment-expression ]

and trying to explain the fact that it allows an assignment expression,
and not merely a conditional-expression. However, the
type-qualifier-list and 'static' are only meaningful in the leading
dimension of a function parameter declaration (though they seem to be
allowed, syntactically at least, in other contexts?). Because of the
clause that you cite, an assignment expression that is NOT an integer
constant expression is equivalent to '*' at function prototype scope,
and therefore doesn't actually get executed.

Therefore, those two features can only meaningfully co-exist in a
function definition, where the array declaration has block scope, rather
than function prototype scope:

int i;
int func(int array[static const i=100])
{
// body of function
};

I think this means that i=100 gets executed every time func() is called
- but I'm not entirely sure of that.

> Incidentally, by not being a constant expression makes
> array into a VLA. I suspect the OP had no intention of doing so,
> i.e. the closest correction of their example is probably just:
>
> int func(array[static 100]);

As I understood it, he's not trying to do anything specific with these
features, he's just trying to figure out what the grammar means.

Ben Bacarisse

unread,
Sep 13, 2012, 5:04:34 PM9/13/12
to
The standard uses assignment-expression in other places (in particular
in initialisers) because it is the most general syntactic quantity that
does not include the comma operator. My guess is that it's used here to
make this syntax as general as possible without allowing for something
that looks a bit like an odd initialisation:

f(a[static const i = 100, 42]); // not allowed and looks weird

I know that inside the [] the comma would be unambiguous, but my guess
is that the committee was motivated by the syntax of initialisation.

I'd be surprised (but pleasantly surprised) if putting an actual
assignment there was ever considered to be of practical value. (In
fact, I'd consider putting anything there that has a side effect to be
deliberate obfuscation.)

<snip>
> Therefore, those two features can only meaningfully co-exist in a
> function definition, where the array declaration has block scope, rather
> than function prototype scope:
>
> int i;
> int func(int array[static const i=100])
> {
> // body of function
> };

(; not permitted here)

> I think this means that i=100 gets executed every time func() is called
> - but I'm not entirely sure of that.

I think so too, but I hope I never see a side effect in that position
in real code!

<snip>
--
Ben.

James Kuyper

unread,
Sep 13, 2012, 5:30:27 PM9/13/12
to
On 09/13/2012 05:04 PM, Ben Bacarisse wrote:
> James Kuyper <james...@verizon.net> writes:
...
>> I was concentrating on the grammar for array declarations, which says:
>>
>> D[ static type-qualifier-listopt assignment-expression ]
>> D[ type-qualifier-list static assignment-expression ]
>>
>> and trying to explain the fact that it allows an assignment expression,
>> and not merely a conditional-expression.
>
> The standard uses assignment-expression in other places (in particular
> in initialisers) because it is the most general syntactic quantity that
> does not include the comma operator. My guess is that it's used here to
> make this syntax as general as possible without allowing for something
> that looks a bit like an odd initialisation:
>
> f(a[static const i = 100, 42]); // not allowed and looks weird

If a statement that actually performs an assignment were not intended to
be allowed there, they should have used conditional-expression instead
pf assignment-expression. The syntax allows it, and the semantics give
it an unambiguous meaning when it occurs anywhere other than the
parameter list of a function definition. I think I know what the meaning
is in that context, too, but I'm not quite sure.

> I know that inside the [] the comma would be unambiguous, but my guess
> is that the committee was motivated by the syntax of initialisation.
>
> I'd be surprised (but pleasantly surprised) if putting an actual
> assignment there was ever considered to be of practical value. (In
> fact, I'd consider putting anything there that has a side effect to be
> deliberate obfuscation.)

Being "pleasantly surprised" by such a feature seems inconsistent with
calling any use of it "obfuscation".

>> Therefore, those two features can only meaningfully co-exist in a
>> function definition, where the array declaration has block scope, rather
>> than function prototype scope:
>>
>> int i;
>> int func(int array[static const i=100])
>> {
>> // body of function
>> };
>
> (; not permitted here)
>
>> I think this means that i=100 gets executed every time func() is called
>> - but I'm not entirely sure of that.
>
> I think so too, but I hope I never see a side effect in that position
> in real code!

I was trying to keep my example close to the OP's code. However, the
following code relies upon the same feature to do something that feels a
(little) bit better motivated:

static size_t last_n;

int func(size_t n, double array[static const last_n=n])
{
// body of function
}

If I'm correct about what this code does, it is essentially equivalent to

int func(size_t n, double array[static const n])
{
last_n = n;
// body of function
}

Ben Bacarisse

unread,
Sep 13, 2012, 11:05:46 PM9/13/12
to
James Kuyper <james...@verizon.net> writes:

> On 09/13/2012 05:04 PM, Ben Bacarisse wrote:
>> James Kuyper <james...@verizon.net> writes:
> ...
>>> I was concentrating on the grammar for array declarations, which says:
>>>
>>> D[ static type-qualifier-listopt assignment-expression ]
>>> D[ type-qualifier-list static assignment-expression ]
>>>
>>> and trying to explain the fact that it allows an assignment expression,
>>> and not merely a conditional-expression.
>>
>> The standard uses assignment-expression in other places (in particular
>> in initialisers) because it is the most general syntactic quantity that
>> does not include the comma operator. My guess is that it's used here to
>> make this syntax as general as possible without allowing for something
>> that looks a bit like an odd initialisation:
>>
>> f(a[static const i = 100, 42]); // not allowed and looks weird
>
> If a statement that actually performs an assignment were not intended to
> be allowed there, they should have used conditional-expression instead
> pf assignment-expression. The syntax allows it, and the semantics give
> it an unambiguous meaning when it occurs anywhere other than the
> parameter list of a function definition. I think I know what the meaning
> is in that context, too, but I'm not quite sure.

I don't find that compelling. It would be more compelling if you could
suggest why the syntax does not permit a full expression.

>> I know that inside the [] the comma would be unambiguous, but my guess
>> is that the committee was motivated by the syntax of initialisation.
>>
>> I'd be surprised (but pleasantly surprised) if putting an actual
>> assignment there was ever considered to be of practical value. (In
>> fact, I'd consider putting anything there that has a side effect to be
>> deliberate obfuscation.)
>
> Being "pleasantly surprised" by such a feature seems inconsistent with
> calling any use of it "obfuscation".

You take no pleasure in seeing obscure but useful syntax? If there were
are real use I'd find it delightful, no matter how obscure it makes the
code. I might even feel obliged to argue against it's use, but the
delight would remain.

<snip>
--
Ben.
0 new messages