Call a function without argument, although it needs one [K&R-C] - c

It's K&R-C and here is the code: http://v6shell.org/history/if.c
Look at the main-Method. There is this line "if(exp())".
But the function exp is declared as: exp(s). So it needs an argument.
Why does this work? And why would you do this?

Ultimately, it is a bug in the Unix V6 shell support command, if.
The code for the function is:
exp(s) {
int p1;
p1 = e1();
if (eq(nxtarg(), "-o")) return(p1 | exp());
ap--;
return(p1);
}
The function parameter s, implicitly of type int (as is the function iteself), is actually unused in the function, so the bug is the presence of s, not the absence of an argument in the calls to exp(). All the calls with zero actual arguments are correct.

If you look at the definition:
exp(s) {
int p1;
p1 = e1();
if (eq(nxtarg(), "-o")) return(p1 | exp());
ap--;
return(p1);
}
s is not used
C doesn't require compile time type checking. It doesn't even require function parameters to be checked. Everything is a/series of bytes
Why does C not do any of those checks? From what I hear it's 'cause during first few years of C, computers were fairly weak. Doing those checks would require multiple passes to scan the source code, which basically increases compile time by a magnitude of n passes. So it just does a single pass, and takes every name as is, which is why function overloading is not supported
So if the definitions did make use of s in some way, you would most likely get some horrible runtime error with wonderful outputs to the console

This is because in c
The compiler will not be able to perform compile-time checking of argument types and arity when the function is applied to some arguments. This can cause problems
Calling an undeclared function is poor style in C (See this) and illegal in C++
for example-
#include<stdio.h>
void f(int x);
int main()
{
f(); /* Poor style in C, invalid in C++*/
getchar();
return 0;
}
void f(int x)
{
printf("%d", x);
}
This program will work but shouldn't be used.See this Wiki link for more.

Related

C function weird syntax [duplicate]

I'm relatively new to C. I've come across a form of function syntax I've never seen before, where the parameter types are defined after that parameter list. Can someone explain to me how it is different than the typical C function syntax?
Example:
int main (argc, argv)
int argc;
char *argv[];
{
return(0);
}
That's the old-style syntax for parameter lists, which is still supported. In K&R C you could also leave off the type declarations and they would default to int. i.e.
main(argc, argv)
char *argv[];
{
return 0;
}
would be the same function.
What's also interesting is the calling convention difference of functions with, and functions without a prototype. Consider an old style definition:
void f(a)
float a; {
/* ... */
}
In this case, the calling convention is that all arguments are promoted before being passed to the function (for example, a float argument is first promoted to double, before being passed). So if f receives a double but the parameter has type float (which is perfectly valid) the compiler has to emit code that converts the double to a float prior to executing the function's body.
If you include a prototype, the compiler does not do such automatic promotions anymore and any data passed is converted to the types of the parameters of the prototype as if by assignment. So the following is not legal and results in undefined behavior:
void f(float a);
void f(a)
float a; {
}
In this case, the function's definition would convert the submitted parameter from double (the promoted form) to float because the definition is old-style. But the parameter was submitted as a float, because the function has a prototype. For example, clang gives
main.c:3:9: warning: promoted type 'double' of K&R function parameter is not compatible with the parameter type 'float' declared in a previous prototype [-Wknr-promoted-parameter]
Your options of solving the contradictions are the two following:
// option 1
void f(double a);
void f(a)
float a; {
}
// option 2
// this declaration can be put in a header, but is redundant in this case,
// since the definition exposes a prototype already if both appear in a
// translation unit prior to the call.
void f(float a);
void f(float a) {
}
Option 2 should be preferred if you have the choice because it gets rid of the old style definition up front. If such contradicting function types for a function appears in the same translation unit, the compiler will usually tell you (but is not required). If such contradictions appear over multiple translation units, the error will possibly go unnoticed and can result in hard to predict bugs. It is best to avoid these old style definitions.
This is the so caller K&R style or old-style declaration.
Note, that this declaration is significantly different from the modern declaration. K&R declaration does not introduce a prototype for the function, meaning that it doesn't expose the types of the parameters to the outside code.
There is no difference, it is just that that is the old syntax for function declarations in C -- it was used pre ANSI. Never write such code unless you plan to give it to your friends from the 80's. Also, never depend upon implicit type assumptions (as another answer seems to suggest)
While the old syntax for function definition still works (with warnings, if you ask your compiler), using them does not provide function prototypes.
Without function prototypes the compiler will not check if the functions are called correctly.
#include <stdio.h>
int foo(c)
int c;
{ return printf("%d\n", c); }
int bar(x)
double x;
{ return printf("%f\n", x); }
int main(void)
{
foo(42); /* ok */
bar(42); /* oops ... 42 here is an `int`, but `bar()` "expects" a `double` */
return 0;
}
When the program is run, the output on my machine is
$ gcc proto.c
$ gcc -Wstrict-prototypes proto.c
proto.c:4: warning: function declaration isn’t a prototype
proto.c:10: warning: function declaration isn’t a prototype
$ ./a.out
42
0.000000
Its just the same but old fashion. You probably found it is some old, legacy code.
Old or not, I would argue what is old and what not.. like the pyramids are ancient, but none of today’s so-called scientists have a clue how they were made. Looking back, old programs still work today without memory leaks, but these "new" programs tend to fail more than often. I see a trend here.
Probably they saw functions as structs which have an executable body. Knowledge of ASM is needed here to solve the mystery.
Edit, found a macro which indicates you do not need to supply argument names at all.
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
#ifndef Z_ARG /* function prototypes for stdarg */
# if defined(STDC) || defined(Z_HAVE_STDARG_H)
# define Z_ARG(args) args
# else
# define Z_ARG(args) ()
# endif
#endif
Here is an usage example, library is zlib-1.2.11.
ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
So my second guess would be for function overloading, otherwise these arguments had no use. One concrete function, and now infinite amount of functions with same name.

Pointer to void as an argument in a function with no prototype for variable number of arguments

Say I have a function that should accept any number of parameters, so what im coing here is declaring no prototype, and letting the function to be created when it is called in the code. I am using a pointer to void to receive the random number of parametersparameters, however, when doing this, the reference to the memory addres of the first parameter is the only thing that is passed, so for it to work, i would have to declare variables in the same order that i am going to call them in the code:
unsigned char result=0;
unsigned char a=1;
unsigned char b=2;
unsigned char c=3;
char main (void)
{
for (;;)
{
result = function (&a, &b, &c);
result = function (&c, &b, &a);
}
}
function (void *vPointer)
{
return (1);
}
Also I am declaring function without a type since it would not match the call (where it is implicitly declared also).
The result here is a reference to the first parameter sent in the function, so if i point to the next addres in the first function call, it would work, but in the second call, it gets the reference to c, and whatever memory is ahead of where it is placed.
Anyone know a way of sorting the parameters references the correct way? or an effective way to receive an unknown number of parameters in a function?
NOTE: (...) SHALL NOT be used.
All C functions should have prototypes. They're not actually mandatory, but there's no good reason not to use them (unless you're stuck with a pre-ANSI compiler that doesn't support them). (But see the bottom of this answer.)
If you want a function that takes a variable number of arguments, that prototype should end with , ..., and the function itself should use the <stdarg.h> mechanism to process its arguments. (This requires at least one argument with a defined type; that argument is used as an anchor for the following arguments.) It's documented here and elsewhere.
As I was typing this, you updated your question with "NOTE: No libraries (such as (...) )should be used". <stdarg.h> is one of the handful headers that's required for all conforming C implementations, including freestanding (embedded) ones -- because it doesn't define any functions, just types and macros. Your C implementation should support it. If it doesn't, then it's not a conforming C implementation, and you'll need to tell us exactly what compiler you're using and/or read its documentation to find out how it handles variadic functions, or an equivalent.
If you really can't use , ... and <stdarg.h>, (or perhaps the older <varargs.h>), then you can define your function with a fixed number of arguments, enough for all uses, then have callers pass extra null pointers.
EDIT:
This is an update based on new information in comments and chat.
The OP has a homework assignment to implement printf for some TI microcontroller, for some reason not using either the , ... notation or <stdarg.h>. The compiler in question apparently implements C89/C90, so it does support both features; this is an arbitrary restriction.
This information should have been in the question, which is why I'm downvoting it until the OP updates it.
There is no portable way to achieve this -- which is exactly why , ... is part of the standard language, and <stdarg.h> is part of the standard library.
Probably the best approach would be to write a program that uses , ... and <stdarg.h>, then invoke the compiler so it shows just the output of the preprocessor (resolving the various va_* macros and the va_list type), and then imitate that. And you'd have to assume, or verify using the compiler documentation, that the calling convention for variadic and non-variadic functions is compatible. In other words, find out what this particular implementation does, and reinvent a similar wheel.
(I hope that the point of the homework assignment is to demonstrate how much better the standard techniques are.)
UPDATE 2:
I wrote above that all C functions should have prototypes. This may actually be a rare exception to this rule. At least one of these calls:
printf("Hello\n");
printf("x = %d\n", 42);
must produce a diagnostic from a conforming compiler unless either printf is declared with , ... (which is forbidden by the homework assignment), or there is no visible prototype for printf. If there's no prototype, then at least one of the calls will have undefined behavior (behavior that's not defined by the C standard, though it may be defined by a particular compiler).
In effect, to meet the homework requirements, you'll have to pretend that you're using a pre-ANSI C compiler.
the only "clean" way to use functions with variable arguments is to use variadic functions:
#include <stdarg.h>
void myfun(int foo, ...) {
va_list ap;
va_start(foo, ap);
// ...
va_end(ap);
}
you will need to make sure that you know which arguments you actually expect (usually you either use your first argument to indicate how many (and which) arguments to expect (examples are an int that says "now come arguments", or a format-string like "%d %s:%s", that says now come an int and two char*), or you use a a final terminating argument (e.g. read arguments until you encounter NULL).
You could use an array of variable length:
unsigned char result=0;
unsigned char a=1;
unsigned char b=2;
unsigned char c=3;
function (int len, void *vPointer);
int main (void)
{
for (;;)
{
unsigned char args[3];
args[0] = a;
args[1] = b;
args[2] = c;
result = function (3, args);
args[0] = c;
args[1] = b;
args[2] = a;
result = function (3, args);
}
return 0;
}
function (int len, void *vPointer)
{
return (1);
}
But I recommend you use the standard way instead, i.e. variadic functions.
//jk
You can use a structure:-
typedef struct _Params {
int m_a;
int m_b;
int m_c;
} Params;
Then your parameters can't get mixed up. Just as more letters up to the max you need.

Why is a function declared near the top of a source file?

I'm working through K & R to learn programming. Going well so far, but I'm unclear about the role of a line of code from section 1.8 (functions).
In section 1.8, the authors show you how to create a function to raise one integer to the power of another integer.
I've pasted the code below, as it was written in the book. Everything outputs fine. But I don't know why they've included this line at the top:
int power(int m, int n);
The book doesn't mention it, apart from saying that the program will raise integer m to the power n. If I remove the line from the code, the program still outputs as it should.
If I understand this correctly, the line
int power(int base, int n)
creates the function, and the braces underneath define the function. Then the braces under main call the function to output the chart.
So all that seems to make sense. But I don't see what the very top line does.
It could be extraneous, but it seems far more likely that I'm missing something. Can anyone enlighten me as to why that line is there?
#include <stdio.h>
int power(int m, int n);
/* test power function */
main()
{
int i;
for (i = 0; i < 10; ++i)
printf("%d %d %d\n", i, power(2,i), power(-3, i));
return 0;
}
/* power: raise base to n-th power; n >= 0 */
int power(int base, int n)
{
int i, p;
p = 1;
for (i = 1; i <= n; ++i)
p = p * base;
return p;
}
The first line is the declaration of the function. The block of code at the bottom is the definition of the function.
Starting with the 1999 version of the ISO C standard, it's illegal (a constraint violation) to call a function without a visible declaration; the declaration must precede the call.
For a simple program like this one, you could just write the full definition of power() before the definition of main() (since a definition also provides a declaration), but for more complex cases (such as recursive calls) you often need to provide a separate declaration.
For larger programs, it's common to collect all the function declarations in a header file (foo.h, for example), and the corresponding definitions in a source file (foo.c, for example). A #include "foo.h" directive is used to make the declarations visible in other files. You'll see that kind of thing later in the book.
(In the 1990 and earlier versions of C, which is what K&R2 covers, there are cases where you can call a function without a visible declaration -- but it's still a very good idea to provide explicit declarations anyway.)
Incidentally, the declaration of the main program should really be int main(void) rather than just main().
Terminology: a "prototype" is a function declaration that specifies the types of the parameters.
int power(int base, int n); /* a declaration that's also a prototype */
int power(int, int); /* likewise */
int power(); /* a declaration but not a prototype */
(Parameter names are required in a definition, but optional in a standalone declaration.)
As a special case, a prototype for a function with no parameters uses (void), since empty parentheses already mean a non-prototype declaration. So int main(void) is a prototype, but int main() isn't.
Non-prototype declarations are "obsolescent", meaning that they could in theory be removed from a future language standard. But they've been obsolescent since 1989, and even in the new 2011 ISO C standard the committee hasn't seen fit to remove them.
int power(int m, int n);
is a declaration of the power function in its prototype form. A function declaration informs the compiler of the number of parameters the function has, the type of the function parameters and the type of the function return value.
In C you cannot use a function identifier before it has been declared.
It's a forward declaration which makes the function interface public as the function is used before it is actually implemented below main().
Header files, which you #include provide a similar functionality of making the callable API public---but the code is then commonly supplied in a library rather than via the same compilation unit as it is here in this single-file example of the K&R Intro chapter.
If you don't include that line at the top, when the program reaches power(2,i) in main power has not been declared yet. Programs are read from top to bottom, and by putting the declaration at the top, the compiler knows that "a definition is coming".
That line is just the function prototype. It's a forward declaration that allows code to be able to use some function with that signature that will exist when everything is linked together. Without it, the main() function will attempt to use the power() function but the compiler is not aware of it yet since it isn't actually defined later in the source file.
That line at the top that you are referring to is a function prototype. The ONLY thing it is there for is so that the compiler can check your work, that is, to make sure you are using the function correctly by passing the right types and number of arguments. That's all it is for. That is why you can remove it and the code still compiles - all you are doing by removing it is removing the compiler's reference so it can't check your work. And if you do remove it, then there is the possibility that you could pass the wrong type of argument(s) and cause a hard to find run time error or program crash. But leaving it in allows the compiler to flag such an error at compile time saving you some grief. And saving someone some grief is a good thing.
Later, with the C99 standard, they decided to make it mandatory to provide a function prototype (or else define the function first) in order for the code to compile, thus forcing you to let the compiler check your work.

Is c function prototype mismatch merely a warning

please take a look at my codes below
#include <stdio.h>
void printOut()
{
static int i = 0;
if (i < 10)
{
printOut(i);
}
}
int main(int argc, char *argv[])
{
return 0;
}
i guess there should be an error due to my invoking the non-existed function prototype.Actually, the code compiles well with mingw5 compiler, which is weird for me, then i change to Borland Compiler, i get a warning message said that no printOut function prototype, is this only a warning ? What is more, the code executes well without any pop-up error windows.
In C, a function without any parameters can still take parameters.
That's why it compiles. The way to specify that it doesn't take any parameters is:
void printOut(void)
This is the proper way to do, but is less common especially for those from a C++ background.
Your program's behavior is undefined, because you define printOut() with no parameters, but you call it with one argument. You need to fix it. But you've written it in such a way that the compiler isn't required to diagnose the problem. (gcc, for example, doesn't warn about the parameter mismatch, even with -std=c99 -pedantic -Wall -Wextra -O3.)
The reasons for this are historical.
Pre-ANSI C (prior to 1989) didn't have prototypes; function declarations could not specify the expected type or number of arguments. Function definition, on the other hand, specified the function's parameters, but not in a way that the compiler could use to diagnose mismatched calls. For example, a function with one int parameter might be declared (say, in a header file) like this:
int plus_one();
and defined (say, in the corresponding .c file) like this:
int plus_one(n)
int n;
{
return n + 1;
}
The parameter information was buried inside the definition.
ANSI C added prototypes, so the above could written like this:
int plus_one(int n);
int plus_one(int n)
{
return n + 1;
}
But the language continued to support the old-style declarations and definitions, so as not to break existing code. Even the upcoming C201X standard still permits pre-ANSI function declarations and definitions, though they've been obsolescent for 22 years now.
In your definition:
void printOut()
{
...
}
you're using an old-style function definition. It says that printOut has no parameters -- but it doesn't let the compiler warn you if you call it incorrectly. Inside your function you call it with one argument. The behavior of this call is undefined. It could quietly ignore the extraneous argument -- or it could conceivably corrupt the stack and cause your program to die horribly. (The latter is unlikely; for historical reasons, most C calling conventions are tolerant of such errors.)
If you want your printOut() function to have no parameters and you want the compiler to complain if you call it incorrectly, define it as:
void printOut(void)
{
...
}
This is the one and only correct way to write it in C.
Of course if you simply make this change in your program and then add a call to printOut() in main(), you'll have an infinite recursive loop on your hands. You probably want printOUt() to take an int argument:
void printOut(int n)
{
...
}
As it happens, C++ has different rules. C++ was derived from C, but with less concern for backward compatibility. When Stroustrup added prototypes to C++, he dropped old-style declarations altogether. Since there was no need for a special-case void marker for parameterless functions, void printOut() in C++ says explicitly that printOut has no parameters, and a call with arguments is an error. C++ also permits void printOut(void) for compatibility with C, but that's probably not used very often (it's rarely useful to write code that's both valid C and valid C++.) C and C++ are two different languages; you should follow the rules for whichever language you're using.

Please explain How prog works

#include<stdio.h>
int f();
int main()
{
f(1);
f(1,2);
f(1,2,3);
}
f(int i,int j,int k)
{
printf("%d %d %d",i,j,k);
}
it is running fine(without any error) ...can u plz explain how it executes ?
how f(1) and f(1,2) links to f(int,int,int) ?
You must have a different definition of "error" to me :-) What gets printed the first two times you call your f function? I get
1 -1216175936 134513787
1 2 134513787
1 2 3
for my three function calls.
What you're seeing is a holdover from the very early days of C when people played footloose and fancy-free with their function calls.
All that is happening is that you are calling a function f and it's printing out three values from the stack (yes, even when you only give it one or two). What happens when you don't provide enough is that your program will most likely just use what was there anyway, usually leading to data issues when reading and catastrophic failure when writing.
This is perfectly compilable, though very unwise, C. And I mean that in a very real, "undefined behaviour", sense of the word (referring specifically to C99: "If the expression that denotes the called function has a type that does not include a prototype, ... if the number of arguments does not equal the number of parameters, the behaviour is undefined").
You should really provide fully formed function prototypes such as:
void f(int,int,int);
to ensure your compiler picks up this problem, and use ellipses (...) in variable parameter functions.
As an aside, what usually happens under the covers is that the calling function starts with a stack like:
12345678
11111111
and pushes (for example) two values onto a stack, so that it ends up like:
12345678
11111111
2
1
When the called function uses the first three values on the stack (since that's what it wants), it finds that it has 1, 2 and 11111111.
It does what it has to do then returns and the calling function clears those two values off the stack (this is called a caller-makes-good strategy). Woe betide anyone who tries this with a callee-makes-good strategy :-) although that's pretty unusual in C since it makes variable argument functions like printf a little hard to do.
This declaration:
int f();
...tells the compiler "f is a function that takes some fixed number of arguments, and returns int". You then try to call it with one, two and three arguments - C compilers are conceptually one-pass (after preprocessing), so at this point, the compiler doesn't have the information available to argue with you.
Your actual implementation of f() takes three int arguments, so the calls which only provide one and two arguments invoke undefined behaviour - it's an error which means that the compiler isn't required to give you an error message, and anything could happen when you run the program.
int f();
In C this declares a function which take a variable number of arguments i.e. it's equivalent to the following in C++
int f(...);
To check this use the following instead of int f();
int f(void);
This will cause the compiler to complain.
Please note: A C linker quirk is also involved here...the C linker does not validate the arguments being passed to a function at the point of invocation and simply links to the first public symbol with the same name. Thus the use of f() in main is allowed because of the declaration of int f(). But the linker binds the function f(int, int, int) during link time at the invocation sites. Hope that makes some sense (please let me know if it doesn't)
It runs fine since int f() means what other answer has already said: it means unspecified number of arguments. This mean you can call it with the number of arguments that you want (also more than 3), without the compiler saying anything about it.
The reason why it works "under the cover", is that arguments are pushed on the stack, and then accessed "from" the stack in the f function. If you pass 0 arguments, the i, j, k of the function "corresponds" to values on the stack that, from the function PoV, are garbage. Nonetheless you can access their values. If you pass 1 argument, one of the three i j k accesses the value, the others get garbage. And so on.
Notice that the same reasoning works if the arguments are passed in some other way, but anyway these are the convention in use. Another important aspect of these conventions is that the callee is not responsible for adjusting the stack; it is up to the caller, that knows how many argument are pushed for real. If it would be not so, the definition of f could suggest that it has to "adjust" the stack to "release" three integer, and this would cause a crash of some kind.
What you've written is fine for the current standard (on gcc compiles with no warnings even with -std=c99 -pedantic; there's a warning, but it's about the missing int in front of the f definition), even though many people finds it disgusting and call that an "obsolescent feature". For sure, your usage in the example code does not show any usefulness, and likely it can help busting bugs a more binding usage of prototypes! (But still, I prefer C to Ada)
add
A more "useful" usage of the "feature" that does not trigger the "undefined behaviour" issue, could be
#include<stdio.h>
int f();
int main()
{
f(1);
f(2,2);
f(3,2,3);
}
int f(int i,int j,int k)
{
if ( i == 1 ) printf("%d\n", i);
if ( i == 2 ) printf("%d %d\n", i, j);
if ( i == 3 ) printf("%d %d %d\n", i, j, k);
}
When you compile the same program using g++ compiler you see the following errors -
g++ program.c
program.c: In function `int main()':
program.c:2: error: too many arguments to function `int f()'
program.c:6: error: at this point in file
program.c:2: error: too many arguments to function `int f()'
program.c:7: error: at this point in file
program.c:2: error: too many arguments to function `int f()'
program.c:8: error: at this point in file
program.c: At global scope:
program.c:12: error: ISO C++ forbids declaration of `f' with no type
Using gcc with option -std=c99 just gives a warning
Compile the same program with the same standard which g++ is having by default, gives the following message:
gcc program.c -std=c++98
cc1: warning: command line option "-std=c++98" is valid for C++/ObjC++ but not for C
My answer then would be or c compilers conform to a different standard which is not as restrictive as the one which c++ conforms to.
In C a declaration has to declare at least the return type. So
int f();
declares a function that returns the type int. This declaration doesn't include any information about the parameters the function takes. The definition of the function is
f(int i,int j,int k)
{
printf("%d %d %d",i,j,k);
}
Now it is known, that the function takes three ints. If you call the function with arguments that are different from the definition you will not get a compile-time error, but a runtime error (or if you don't like the negative connotation of error: "undefined behavior"). A C-compiler is not forced by the standard to catch those inconsistencies.
To prevent those errors, you should use proper function prototypes such as
f(int,int,int); //in your case
f(void); //if you have no parameters

Resources