3

At C lang FAQ I found the following code:

void f(ipp)
int **ipp;
{
    static int dummy = 5;
    *ipp = &dummy;
}

I tested compiling it with -Wall -std=c11 -pedantic flags, and it compiled with no warnings or errors. How is that possible - a variable declared between the function name and its block?

Edit:

A few hours after posting, and after a number of answers, I find the question is closed as a duplicate. I don't agree with the decision to close. In fact, the duplicate Q&A and the answers given here so far, although broadly correct, don't answer my question specifically.

My query is about variable declarations appearing between a function name and its block. OK, that's the original K&R style, but I still find the location of the declarations shocking. Having read the K&R Second Edition book that describes ANSI C89, I was aware that the previous style allowed a different way of declaring function parameters, but AFAIK that book did not show the declarations being made in this way. Maybe it does and I have forgotten about it.

I believe it is good to have a question separately about this particular issue in case someone else gets thrown by it in the future. My question should stand for anyone who can shed some light on how it was decided to allow the parameters be declared in this strange location. The impression you get from C and all C-inspired languages is that nothing comes between a token and its block braces. My question draws attention to a significant exception that should be highlighted and its rationalle understood, even if it is 30/40 years old.

Edit 2:

I now find that C++ syntax allows for a token to come between the function name and its block. Even so, the idea of whole declaration lines coming in between is more severe and worth pointing out to C newbies as a quirk they might encounter. I have checked, and the K&R Second Edition book indeed does not explicitly mention this.

Theo d'Or
  • 783
  • 1
  • 4
  • 17
  • 3
    It's legacy syntax from pre-ansi C. That used to be the way function arguments were declared, before function prototypes were added. – Tom Karzes Nov 14 '19 at 13:05
  • Thank you! That must mean that the FAQ is outdated. But given the flags that I used, I would still expect this to fail. I'm using GCC. If you write up your comment as full answer, I will accept it. – Theo d'Or Nov 14 '19 at 13:08
  • 1
    If you see something like this nowadays it can mean: someone was learning C from almost 40y old C book or was hibernating last 30-40y in the cryogenic capsule – 0___________ Nov 14 '19 at 13:10

4 Answers4

5

It's not any variable, it's the function argument. Just another programming style, called K&R style.

Some additional read on this.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
3

This syntax is deprecated since a long time but in C17 it is still valid. The removal of this feature has recently been voted into C2x, see point 6.30:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2451.pdf

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • 1
    Thank you, especially for providing a link to the PDF detailing the future direction for C. I have deleted my original comment in reply to your answer, where I claimed that with my attention being drawn to the original K&R style, I liked it and could see its uses. I commented too early - that style really does not have anything to recommend it. – Theo d'Or Nov 14 '19 at 17:05
1

In general the function definition is defined in the C Standard the following way

function-definition:
    declaration-specifiers declarator declaration-listopt compound-statement

declaration-list:
    declaration
    declaration-list declaration

Such a function definition that contains the declaration-list is named as a function definition with an identifier list opposite to the function definition with a parameter type list.

So in the function declarator there is used a list of identifiers

void f(ipp)
       ^^^^

that need to be declared before the body of the function

void f(ipp)
int **ipp;
^^^^^^^^^

It is an old style of function definitions that is not recommended to use because such definitions do not provide a function prototype that can be checked by the compiler.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

From the C11 standard:

6.7.6 Declarators:
1.direct-declarator (parameter-type-list)
2.direct-declarator (identifier-list)

As you can see, the standard specifies two ways of declaring functions.

The first involves typed parameters where each parameter is given a specific type.

The second involves an identifier list where parameter names are supplied inside the enclosing parenthesis without being given data types.

As a result, your code is valid C11 and compiles fine as it should be expected.

machine_1
  • 4,266
  • 2
  • 21
  • 42