Is it standard C17 to wrap a parameter in a function declaration in parenthesis
Asked Answered
A

2

5

Is the following a standard C function declaration according to ISO/IEC 9899:2017 (c17)?

int foo(int (bar), int (baz));

If so, please point me to the section in the standard that defines this.

In N2310 Appendix Phrase structure grammar, A.2.2 Declarations, Section 6.7.6, I see the following:

parameter-list:
    parameter-declaration
    parameter-list , parameter-declaration

I'm not familiar with this type of grammar expression, so I'm not sure how to interpret it.

The following program compiles without errors with gcc --std=c17 -Wall and clang --std=c17 -Wall

static int foo(int (bar), int (baz));
static int foo(int bar, int baz)
{
        return bar + baz;
}
int main() {
        return foo(1, 2);
}

However if I run cppcheck (a static analysis tool) on this program, it appears to parse incorrectly.

I'm most interested if this grammar is standard C, or a compiler-specific behavior so I can try to fix the parser or submit a bug report if I can't.

Acephalous answered 14/3 at 21:16 Comment(5)
Isn't N2310 a very early C23 draft?Sophist
@TedLyngmo I noticed that after my (deleted) comment: 2017 becomes 202x. I've had N2310 since 2019.Bigner
It's even necessary sometimes. int (*a)[5] (a pointer to an array) is not the same as int *a[5] (an array of pointers)Stelle
cppcheck -- It's hard for me to put much faith in a program that seems to think there is a language named "C/C++". I would be inclined to wonder what it does with code that is valid in one those two distinct languages but not in the other. Or with code that is valid in both but means different things in the two.Cause
int (x); for plain variables is also allowed. As is int (x) = (1);. As is int (x)={1};. As is int (x)={(1)};. C is not always a very rational language.Saponaceous
H
8

The declaration is allowed by the standard.

Sectin 6.7.6p1 of the C standard gives the full syntax for a declaration, including the portion you quoted. The relevant parts are as follows:

A parameter-declaration is defined as:

parameter-declaration:

  • declaration-specifiers declarator
  • declaration-specifiers abstract-declaratoropt

A declarator is defined as:

declarator:

  • pointeropt direct-declarator

And a direct-declarator is defined (in part) as:

direct-declarator:

  • ( declarator )

So we can see from the above that a parameter name can be enclosed in parenthesis.

Habitancy answered 14/3 at 21:27 Comment(1)
Might be useful to note that there's nothing specific to C17 (or and other C version) here -- this has been the syntax since C89 and before and has never changed.Lamas
L
5

In this declaration of a function

int foo(int (bar), int (baz));

parameters consist from the type specifier int and declarators ( bar ) and ( baz ).

According to the grammar of the declarator (The C17 Standard, 6.7.6 Declarators)

declarator:
    pointeropt direct-declarator
direct-declarator:
    identifier
    ( declarator )
    //...

As you can see a declarator may be enclosed in parentheses.

And a function declarator looks like

direct-declarator ( parameter-type-list )

where parameter-type-list is defined like

parameter-type-list:
    parameter-list
    parameter-list , ...
parameter-list:
    parameter-declaration
    parameter-list , parameter-declaration

and parameter-declaration is defined like

parameter-declaration:
    declaration-specifiers declarator
    declaration-specifiers abstract-declaratoropt

So the declarators of the parameter-list of the shown above function are correct.

You could even write the function declaration like

int ( foo(int (bar), int (baz)) );

Another example. A function declaration with a parameter that declares a variable length array like for example

void f( size_t m, size_t n, int a[m][n] );

may be rewritten like

void f( size_t m, size_t n, int ( ( ( a )[m] )[n] ) );

though of course the parentheses used in the array declaration are redundant.

Without using parentheses enclosing a declarator it would be impossible for example to declare a pointer to an array or a function like for example

int a[m][n];
int ( *p )[n] = a;

because this declaration

int  *p[n] = a;

declares an array of pointers.

Lunn answered 14/3 at 21:30 Comment(7)
"the parentheses are redundant." --> you can say that again. 😉Diannadianne
@chux-ReinstateMonica The parentheses are redundant.Jillianjillie
@KeithThompson Yes. The redundant humor of the comment didn't come through - unless perhaps you are upping the redundancy.Diannadianne
@chux-ReinstateMonica Yes, I am perhaps upping the redundancy.Jillianjillie
@chux-ReinstateMonica and all: could you provide an example(s) where the parentheses are not redundant?Khadijahkhai
@Khadijahkhai as mentioned by @ikegami, int (*a)[5] vs int *a[5].Furthest
@Khadijahkhai Please reread my answer.Lunn

© 2022 - 2024 — McMap. All rights reserved.