Function Argument declaration question from Programming in C, Stephen Kochan - c

I came across this code in Stephen G Kochan's book, Programming in c. Is this possible?
float absolute_value(x)
float x;
{
-----
-----
}
So, as you can see, the argument x is declared after it's used it the method arguments. This throws an obvious compilation error in G++.
So, which C compiler supports this?

That's the old style K&R format. It's not actually declaring the argument x, rather defining its type. By default, things were int unless otherwise specified.
Back when C was a much simpler language, not that far removed from my beloved BCPL, this was how you gave function arguments their types. None of these prototype stuff that you young whippersnappers take for granted.
Oh yeah, and get off my lawn :-)

This is the original way of declaring the types of function parameters in C. Any properly functioning C compiler is required to accept it. It is not allowed in C++, however, so every properly functioning C++ compiler must reject it (though in both cases, note that some specific combination of compiler flags might be required to achieve proper function). Once upon a time, C compilers only accepted this style, and would reject code like: float absolute_value(float x) {}. This was added (along with function prototypes) while C was being standardized.

Related

Why does a function in C(or Objective C) with no listed arguments allow inputting one argument?

In C when a function is declared like void main(); trying to input an argument to it(as the first and the only argument) doesn't cause a compilation error and in order to prevent it, function can be declared like void main(void);. By the way, I think this also applies to Objective C and not to C++. With Objective C I am referring to the functions outside classes. Why is this? Thanks for reaching out. I imagine it's something like that in Fortran variables whose names start with i, j, k, l, m or n are implicitly of integer type(unless you add an implicit none).
Edit: Does Objective C allow this because of greater compatibility with C, or is it a reason similar to the reason for C having this for having this?
Note: I've kept the mistake in the question so that answers and comments wouldn't need to be changed.
Another note: As pointed out by #Steve Summit and #matt (here), Objective-C is a strict superset of C, which means that all C code is also valid Objective-C code and thus has to show this behavior regarding functions.
Because function prototypes were not a part of pre-standard C, functions could be declared only with empty parentheses:
extern double sin();
All existing code used that sort of notation. The standard would have failed had such code been made invalid, or made to mean “zero arguments”.
So, in standard C, a function declaration like that means “takes an undefined list of zero or more arguments”. The standard does specify that all functions with a variable argument list must have a prototype in scope, and the prototype will end with , ...). So, a function declared with an empty argument list is not a variadic function (whereas printf() is variadic).
Because the compiler is not told about the number and types of the arguments, it cannot complain when the function is called, regardless of the arguments in the call.
In early (pre-ANSI) C, a correct match of function arguments between a function's definition and its calls was not checked by the compiler.
I believe this was done for two reasons:
It made the compiler considerably simpler
C was always designed for separate compilation, and checking consistency across translation units (that is, across multiple source files) is a much harder problem.
So, in those early days, making sure that a function's call(s) matched its definition was the responsibility of the programmer, or of a separate program, lint.
The lax checking of function arguments also made varargs functions like printf possible.
At any rate, in the original C, when you wrote
extern int f();
, you were not saying "f is a function accepting no arguments and returning int". You were simply saying "f is a function returning int". You weren't saying anything about the arguments.
Basically, early C's type system didn't even have a way of recording the parameters expected by a function. And that was especially true when separate compilation came into play, because the linker resolved external symbols based pretty much on their names only.
C++ changed this, of course, by introducing function prototypes. In C++, when you say extern int f();, you are declaring a function that explicitly takes 0 arguments. (Also a scheme of "name mangling" was devised, which among other things let the linker do some consistency checking at link time.)
Now, this was all somewhat of a deficiency in old C, and the biggest change that ANSI C introduced was to adopt C++'s function prototype notation into C. It was slightly different, though: to maintain compatibility, in C saying extern int f(); had to be interpreted as meaning "function returning int and taking unspecified arguments". If you wanted to explicitly say that a function took no arguments, you had to (and still have to) say extern int f(void);.
There was also a new ... notation to explicitly mark a function as taking variable arguments, like printf, and the process of getting rid of "implicit int" in declarations was begun.
All in all it was a significant improvement, although there are still a few holes. In particular, there's still some responsibility placed on the programmer, namely to ensure that accurate function prototypes are always in scope, so that the compiler can check them. See also this question.
Two additional notes: You asked about Objective C, but I don't know anything about that language, so I can't address that point. And you said that for a function without a prototype, "trying to input an argument to it (as the first and the only argument) doesn't cause a compilation error", but in fact, you can pass any number or arguments to such a function, without error.

Implicit int declaration of a variable when type qualifier is specified [duplicate]

If "a function" were compiled separately, the mismatch would not be detected, "the function" would return a double that main would treat as an int... In the light of what we have said about how declarations must match definitions this might seems surprising. The reason a mismatch can happen is that if there is no function prototype, a function is implicitly declared by its first appearance in an expression, such as
sum += "the function"(line);
If a name that has not been previously declared occurs in an expression and is followed by a left parenthesis, it is declared by context to be a function name, the function is assumed to return an int, and nothing is assumed about its arguments.
I apologize beforehand for the ambiguous question, but what does this mean?
By the way this is page 73 chapter 4.3 from Brian W. Kernighan and Dennis M. Ritchie's C Programming Language book, 2nd edition.
K&R2 covers the 1989/1990 version of the language. The current ISO C standard, published in 1999 2011, drops the "implicit int" rule, and requires a visible declaration for any function you call. Compilers don't necessarily enforce this by default, but you should be able to request more stringent warnings -- and you definitely should. In well-written new code, the rule is irrelevant (but it is necessary to understand it).
An example: the standard sqrt() function is declared in <math.h>:
double sqrt(double);
If you write a call without the required #include <math.h>:
double x = 64.0;
double y = sqrt(x);
a C90 compiler will assume that sqrt returns int -- and it will generate code to convert the result from int to double. The result will be garbage, or perhaps a crash.
(You could manually declare sqrt yourself, but that's the wrong solution.)
So don't do that. Always include whatever header is required for any function you call. You might get away with calling an undeclared function if it does return int (and if your compiler doesn't enforce strict C99 or C11 semantics, and if a few other conditions are satisfied), but there's no good reason to do so.
Understanding the "implicit int" rule is still useful for understanding the behavior of old or poorly written code, but you should never depend on it in new code.
Function prototypes were introduced into the language late.
Before prototypes, the compiler would assume that every argument passed to every unknown function should be passed as an integer and would assume that the return value was also an integer.
This worked fine for the few cases where it was correct, but meant people had to write programs in an awkward order so that functions would never rely on unknown functions that did not match this expectation.
When prototypes were introduced into C89 (aka ANSI C or ISO C), the prototypes allow the compiler to know exactly what types of arguments are expected and what types of results will be returned.
It is strongly recommended that you use function prototypes for all new code; when working on an entirely old code base, the prototypes might be harmful. (Or, if the code must be compilable on a pre-ANSI C compiler, then you might wish to leave off the prototypes so it can be built on the ancient software. gcc is the only place I've seen this in a long time.)
It's just stating that if the compiler comes across code that calls an unknown function, then it implicitly treats it as if it had already seen a declared prototype of the form int unknown();

How does defining function variables before { and after function declaration work? [duplicate]

I generated a hash function with gperf couple of days ago. What I saw for the hash function was alien to me. It was something like this (I don't remember the exact syntax) :
unsigned int
hash(str, size)
register char* str;
register unsigned int size;
{
//Definition
}
Now, when I tried to compile with a C++ compiler (g++) it threw errors at me for not having str and size declared. But this compiled on the C compiler (gcc). So, questions:
I thought C++ was a superset of C. If its so, this should compile with a C++ compiler as well right?
How does the C compiler understand the definition? str and size are undeclared when they first appear.
What is the purpose of declaring str and size after function signature but before function body rather than following the normal approach of doing it in either of the two places?
How do I get this function to compile on g++ so I can use it in my C++ code? Or should I try generating C++ code from gperf? Is that possible?
1. C++ is not a superset, although this is not standard C either.
2/3. This is a K&R function declaration. See What are the major differences between ANSI C and K&R C?
.
4. gperf does in fact have an option, -L, to specify the language. You can just use -L C++ to use C++.
The Old C syntax for the declaration of a function's formal arguments is still supported by some compilers.
For example
int func (x)
int x
{
}
is old style (K&R style) syntax for defining a function.
I thought C++ was a superset of C. If its so, this should compile with a C++ compiler as well right?
Nopes! C++ is not a superset of C. This style(syntax) of function declaration/definition was once a part of C but has never been a part of C++. So it shouldn't compile with a C++ compiler.
This appears to be "old-school" C code. Declaring the types of the parameters outside of the parentheses but before the open curl-brace of the code block is a relic of the early days of C programming (I'm not sure why but I guess it has something to do with variable management on the stack and/or compiler design).
To answer your questions:
Calling C++ a "superset" of C is somewhat a misnomer. While they share basic syntax features, and you can even make all sorts of C library calls from C++, they have striking differences with respect to type safety, warnings vs. errors (C is more permissible), and compiler/preprocessor options.
Most contemporary C compilers understand legacy code (such as this appears to be). The C compiler holds the function parameter names sort of like "placeholders" until their type can be declared immediately following the function header name.
No real "purpose" other than again, this appears to be ancient code, and the style back in the day was like this. The "normal" approach is IMO the better, more intuitive way.
My suggestion:
unsigned int hash(register char *str, register unsigned int size)
{
// Definition
}
A word of advice: Consider abandoning the register keyword - this was used in old C programs as a way of specifying that the variable would be stored in a memory register (for speed/efficiency), but nowadays compilers are better at optimizing away this need. I believe that modern compilers ignore it. Also, you cannot use the & (address of) operator in C/C++ on a register variable.

C function calls: Understanding the "implicit int" rule

If "a function" were compiled separately, the mismatch would not be detected, "the function" would return a double that main would treat as an int... In the light of what we have said about how declarations must match definitions this might seems surprising. The reason a mismatch can happen is that if there is no function prototype, a function is implicitly declared by its first appearance in an expression, such as
sum += "the function"(line);
If a name that has not been previously declared occurs in an expression and is followed by a left parenthesis, it is declared by context to be a function name, the function is assumed to return an int, and nothing is assumed about its arguments.
I apologize beforehand for the ambiguous question, but what does this mean?
By the way this is page 73 chapter 4.3 from Brian W. Kernighan and Dennis M. Ritchie's C Programming Language book, 2nd edition.
K&R2 covers the 1989/1990 version of the language. The current ISO C standard, published in 1999 2011, drops the "implicit int" rule, and requires a visible declaration for any function you call. Compilers don't necessarily enforce this by default, but you should be able to request more stringent warnings -- and you definitely should. In well-written new code, the rule is irrelevant (but it is necessary to understand it).
An example: the standard sqrt() function is declared in <math.h>:
double sqrt(double);
If you write a call without the required #include <math.h>:
double x = 64.0;
double y = sqrt(x);
a C90 compiler will assume that sqrt returns int -- and it will generate code to convert the result from int to double. The result will be garbage, or perhaps a crash.
(You could manually declare sqrt yourself, but that's the wrong solution.)
So don't do that. Always include whatever header is required for any function you call. You might get away with calling an undeclared function if it does return int (and if your compiler doesn't enforce strict C99 or C11 semantics, and if a few other conditions are satisfied), but there's no good reason to do so.
Understanding the "implicit int" rule is still useful for understanding the behavior of old or poorly written code, but you should never depend on it in new code.
Function prototypes were introduced into the language late.
Before prototypes, the compiler would assume that every argument passed to every unknown function should be passed as an integer and would assume that the return value was also an integer.
This worked fine for the few cases where it was correct, but meant people had to write programs in an awkward order so that functions would never rely on unknown functions that did not match this expectation.
When prototypes were introduced into C89 (aka ANSI C or ISO C), the prototypes allow the compiler to know exactly what types of arguments are expected and what types of results will be returned.
It is strongly recommended that you use function prototypes for all new code; when working on an entirely old code base, the prototypes might be harmful. (Or, if the code must be compilable on a pre-ANSI C compiler, then you might wish to leave off the prototypes so it can be built on the ancient software. gcc is the only place I've seen this in a long time.)
It's just stating that if the compiler comes across code that calls an unknown function, then it implicitly treats it as if it had already seen a declared prototype of the form int unknown();

Untyped arguments in a C function declaration

Recently I've been looking at the some of the C example code from the online resources of Steven Skiena's "Algorithm Design Manual" and have been baffled by the syntax of some of his function calls. Admittedly it's been a while since did C at uni but I've never encountered untyped function arguments like this:
find_path(start,end,parents)
int start;
int end;
int parents[];
{
if ((start == end) || (end == -1))
printf("\n%d",start);
else {
find_path(starts,parents[end],parents);
printf(" %d",end);
}
}
Is this valid syntax anymore? Are / were there any benefits with this style of function declaration? It seems more verbose than the conventional inline typing of arguments.
They are called K&R style definitions. Don't use them in new code. Even K and R recommend that you stay away from them in "The C Programming Language 2ed".
A note of history: the biggest change between ANSI C and earlier
versions is how functions are declared and defined.
The parameters are named between the parentheses, and their types are
declared before opening the left brace; undeclared parameters are
taken as int.
The new syntax of function prototypes makes it much easier for a
compiler to detect errors in the number of arguments or their types.
The old style of declaration and definition still works in ANSI C, at
least for a transition period, but we strongly recommend that you use
the new form when you have a compiler that supports it.
This is an old style way of giving the function types. It was dropped in the C99 standard and is not appropriate for modern code.
The arguments are typed, just not inline. The types are between the first line and the opening bracket.
Anyway, this style is old and not recommended.
These K&R definitions are the historically traditional way to define functions. In the original C this was the only way to define a function.
Don't use K&R definitions any more. Why not? Because doing so stops the compiler being able to check for type mismatches.
This old syntax stems from the typeless B programming language (and as others stated, is not in standard C anymore):
printn(n,b) {
extrn putchar;
auto a;
if(a=n/b) /* assignment, not test for equality */
printn(a, b); /* recursive */
putchar(n%b + '0');
}
By the way, some compilers may offer a flag that let you compile this oldstyle K+R code.

Resources