gets() takes arguments in C language - c

I have used the gets() function in my program for getting string from user.
When I check gets() with multiple arguments I was shocked.
The gets() takes many number of arguments, but I don't know then number of arguments taken by gets(), and what is the actual use of these all arguments.
void main()
{
char str[10];
printf("Enter the String...:");
gets(str,5,5,5,5,5);
puts(str);
}
The code has no error but it will display the same argument which it is given as input.
input String : This is a Tesing.
output String : This is a Tesing.

gets() takes only one argument.
Probably what happens is that because you didn't include <stdio.h>, the compiler has no idea what the prototype of it, didn't find the compilation error, it happened to work.
The correct form of the whole program should be (even though I'm still using gets()):
#include <stdio.h>
int main() {
char str[10];
printf("Enter the String...:");
gets(str,5,5,5,5,5);
puts(str);
}
When I tested under GCC, it pops an error:
error: too many arguments to function 'gets'
And don't use gets(), it's dangerous and has been removed in C11. Use fgets() instead:
fgets(str, sizeof(str), stdin);
EDIT: thanks for #abelenky's answer and #chux's comment, I confirmed my guess.
In C11 6.5.2.2 Function calls subsection 2 (in Constraints):
**If the expression that denotes the called function has a type that includes a prototype, the number of arguments shall agree with the number of parameters. **Each argument shall
have a type such that its value may be assigned to an object with the unqualified version
of the type of its corresponding parameter.
In subsection 6 (in Semantics):
If the expression that denotes the called function has a type that does not include a
prototype, the integer promotions are performed on each argument, and arguments that
have type float are promoted to double. These are called the default argument promotions. If the number of arguments does not equal the number of parameters, the
behavior is undefined. ...
So what happened is, without the header stdio.h, the compiler doesn't know the prototype of gets(), the behavior is undefined, following subsection 6 above.
With the header, the compiler knows the prototype, according to subsection 2 above, it's required to generate diagnostic message as it's a constraint.

In the C language, you are allowed to pass as many arguments to a function as you want.
(as an example, see printf, which can take an arbitrary number of arguments)
That does not mean that the function you call will use those arguments at all.
Each function will only process the arguments it is documented to process.
Extra arguments are ignored.
So, go ahead, and pass even more arguments to gets. It won't change anything.
gets will still only use the first argument, as it is documented to.

Related

What are the semantics of function pointers with empty parentheses in each C standard?

Answers to this and this question say that function pointers of the form return-type (*pointer)() are pointers to a function which takes any number of arguments, though the latter says they obsolesced in C11.
On an i386 system with GCC, “extra” arguments passed in a call to an empty-parentheses-type’d function pointer are ignored, because of how stack frames work; e.g.,
/* test.c */
#include <stdio.h>
int foo(int arg) { return arg; }
int main(void)
{
int (*fp)() = foo;
printf("%d\n", fp(267239151, 42, (struct { int x, y, z; }){ 1, 2, 3 }));
return 0;
}
$ gcc -o test test.c && ./test
267239151
$
In which C standards are empty-parentheses’d function pointers allowed? and wherever so, what are they specified to mean?
N1570 6.11.6:
The use of function declarators with empty parentheses (not
prototype-format parameter type declarators) is an obsolescent
feature.
This same wording appears in the 1990, 1999, and 2011 editions of the ISO C standard. There has been no change. The word obsolescent says that the feature may be removed in a future edition of the Standard, but so far the committee has not done so. (Function pointer declarations are just one of several contexts where function declarators can appear.)
The Introduction section of the C standard explains what obsolescent means:
Certain features are obsolescent, which means that they may be
considered for withdrawal in future revisions of this International
Standard. They are retained because of their widespread use, but their
use in new implementations (for implementation features) or new
programs (for language [6.11] or library features [7.31]) is
discouraged.
A call to a function declared with an old-style declarator is still required to pass the correct number and type(s) of arguments (after promotion) as defined by the function's actual definition. A call with incorrect arguments has undefined behavior, which means that the compiler is not required to diagnose the error; the burden is entirely on the programmer.
This is why prototypes were introduced, so that the compiler could check correctness of arguments.
On an i386 system with GCC, “extra” arguments passed in a call to an
empty-parentheses-type’d function pointer are ignored, because of how
stack frames work ...
Yes, that's well within the bounds of undefined behavior. The worst symptom of undefined behavior is having the program work exactly as you expect it to. It means that you have a bug that hasn't exhibited itself yet, and it will be difficult to track it down.
You should not depend on that unless you have a very good reason to do so.
If you change
int (*fp)() = foo;
to
int (*fp)(int) = foo;
the compiler will diagnose the incorrect call.
Any function declarator can have empty parentheses (unless it's a function declaration where there is already a non-void prototype in scope). This isn't deprecated, although it is "obsolescent".
In a function pointer, it means the pointer can point to a function with any argument list.
Note that when actually calling a function through the pointer, the arguments must be of correct type and number according to the function definition, otherwise the behaviour is undefined.
Although C allows you to declare a function (or pointer to function) with an empty parameter list, that does not change the fact that the function must be defined with a precise of parameters, each with a precise type. [Note 1]
If the parameter declaration is not visible at a call site, the compiler will obviously not be able to perform appropriate conversions to the provided arguments. It is, therefore, the programmer's responsibility to ensure that there are a correct number of arguments, all of them with the correct type. For some parameter types, this will not be possible because the compiler will apply the default argument promotions. [Note 2]
Calling a function with an incorrect number of arguments or with an argument whose type is not compatible with the corresponding parameter type is Undefined Behaviour.
The fact that the visible declaration has an empty parameter list does not change the way the function is called. It just puts more burden on the programmer to ensure that the call is well-defined.
This is equally true of pointer to function declarations.
In short, the sample code in the question is Undefined Behaviour. It happens to "work" on certain platforms, but it is neither portable nor is it guaranteed to keep working if you recompile. So the only possible advice is "Don't do that."
If you want to create a function which can accept extra arguments, use a varargs declaration. (See open for an example.) But be aware of the limitations: the called function must have some way of knowing the precise number and types of the provided arguments.
Notes
With the the exception of varargs functions, whose prototypes end with .... But a declaration with an empty parameter list cannot be used to call a varargs function.
Integer types narrower than int are converted to int and float values to double.

Enforcing ending variadic function parameters with NULL

Is it possible to make declaration of variadic function so that it doesn't end with "..."?
Today I learned more about exec from unistd.h but through the day I've seen three (two actually) different declaration of execl:
1) int execl ( const char * path, const char * arg0, ..., (char*)NULL ); was shown to us in school and I imagined I would have to end the function call with a NULL value
2) int execl(const char *path, const char *arg, ... /* (char *) NULL */); is what I've found in the exec(3) man page. That would probably mean I still have to end it with a NULL value, but it is not enforced.
3) int execl(const char *path, const char *arg, ...); is what I found here. This one would probably normally put me to rest with the first one being a simplification for students, the second was a varning and this is the real thing (even though I would probably have normally higher regard for both options one and two.)
But then I found on the same site this declaration:
int execle(const char *path, const char *arg, ..., char * const envp[]);
Same question applies, I was unable to create variadic function not ending in ... with gcc telling me that it's expecting ')' before ',' token pointing to the comma after the three dots.
So finally, is it possible to make variadic functions ending with a NULL characters (execl) and if not, is it possible to make it end with predefined variable (execle)?
I tried to compile with gcc 6.3.1, I also tried --std=c11.
Is it possible to make declaration of variadic function so that it doesn't end with "..."?
Is it possible is a slippery question, but consider these facts:
the standard says that "If a function that accepts a variable number of arguments is defined without a parameter type list that ends with the ellipsis notation, the behavior is undefined" (C2011, 6.9.1/8)
Perhaps that answers the question already, but if you choose to mince words and focus on function declarations that are not definitions, then
a function definition is also a declaration
the C language standard requires all declarations of the same function to be "compatible" (else program behavior is undefined) (C2011 6.7/4)
two function declarations with mismatched parameter lists are not compatible (C2011, 6.2.7/3)
Thus, if you declare a variadic function that in fact is also defined, and that function's parameter list does not end with ..., then the program's behavior is undefined.
The documentation you've been reading for execle() and execl() is written to express and discuss those functions' expectations, but to the extent that it seems to present variadic function declarations in which the last element of the parameter list is not ..., those are not actually valid C function declarations.
So finally, is it possible to make variadic functions ending with a NULL characters (execl) and if not, is it possible to make it end with predefined variable (execle)?
It is not possible to describe such calling conventions via conforming C declarations. Variadic functions can have such expectations, and can enforce them at runtime, but they can be enforced at compile time only by a compiler that relies on special knowledge of the functions involved, or on C language extensions that allow such constraints to be described.
The declaration of a variadic function can only specify the required arguments, and the compiler can enforce their types. The variable-length part never has any type checking done. And the variable-length part is always at the end. The declaration for execle() is not meant as an actual C declaration, but just to describe to the programmer how he should construct the arguments.
It's not possible to enforce that the last argument to execl() is NULL. Variadic functions don't know how many arguments were supplied, they determine it from the values of the arguments. printf() assumes that it has enough arguments to fill in all the operators in the format string, and execl() iterates through the arguments until it finds NULL (execle() is similar, but it reads one additional argument to get envp). If you don't end with NULL, it will just keep going, reading garbage and causing undefined behavior.
The declaration you see is the one in the man pages of execl. The declaration for execle in glib is the following: int execle (const char *path, const char *arg, ...). The implementation assumes the last argument is a char**, and uses it for envp. I don't think you can enforce such a rule in C.

consequences of calling a function with fewer arguments in C?

I wrote a function that that takes some argument and a pointer argument . when calling the function , sometimes I need to pass along the pointer for use inside the function and sometimes I don't .
what are the consequences of calling a function with fewer arguments ? it compiles correctly and during runtime its still fine , but is this good programming ? is it better if I call the function with a dummy variable ?
Thanks and sorry for beginner question .
If you call a function with too few arguments and the compiler doesn't complain, then you're doing something wrong.
You can write a function declaration/definition that doesn't specify how many arguments it requires:
void func();
/* ... */
func();
func(arg1);
func(arg1, arg2);
All three of those calls will be accepted by the compiler, but at least two of them are incorrect.
That form of function declaration/definition has been obsolescent since the 1989 ANSI C standard.
Never use this form.
Functions declaration should always be written as prototypes, i.e., declarations that specify the number and type(s) of the parameters. As a special case, (void) denotes a function with no parameters.
void func(int arg);
/* ... */
func(); /* rejected by compiler */
func(arg1); /* accepted -- but only if arg1 is of type int or convertible to int */
func(arg1, arg2); /* rejected by compiler */
If you manage to write code that calls a function with an incorrect number of arguments and get it past the compiler, the behavior is undefined. It might appear to "work", but it could blow up in your face when, for example, you compile it with a different compiler, or with the same compiler and different options.
One complication: some functions are variadic, taking a variable number of arguments. The most common example of this is printf. For variadic functions, the required arguments are typically specified by the function's documentation -- and it's just as important to get the arguments right. The difference is that, for variadic functions, your compiler won't necessarily tell you that a call is incorrect.
The , ... syntax (in the function declaration) and the macros defined in <stdarg.h> are the only legitimate way to write and use C functions that take a variable number and type(s) of arguments.
One of the differences of C++ over plain C is that it incorporates name mangling, which lets you specify a single function with varying return types and parameters. Two functions that share the same name but have different parameters:
int foo();
int foo(int param1, char* param2);
can be done in C++ because it actually alters the name of functions behind-the scenes as it compiles it. When you want to pass in a different number of parameters, it's essentially the same as having two different function names that it calls:
int foo1();
int foo2(int param1, char* param2);
When you pass in fewer parameters than it expects, some compilers should at least throw warnings; others won't even compile the program at all.
Let's say that you pass in 2 parameters to a function that expects 3. When you try to reference that 3rd parameter within your function, what do you expect the value to be? Most of the time, it will be a garbage value, and definitely something your function does not expect.
I would suggest just passing in a dummy value to functions like that: a NULL for a pointer or a 0 or negative "uninitialized" kind of value for other types. You can at least test for those values in your function. Or just write a second function that takes a different number of parameters.
I would not do this. I would only call the function with the declared number of arguments.
It is extremely confusing to the reader of the code.
The reader of the code might even think the function has been overloaded and look
for the other definitions of the function with fewer arguments.
The omitted arguments can have any value at all - anything is considered legal behavior by the C compiler. The program may work perfectly in a test environment and then crash for any or no reason.
If I absolutely had to have a variable number of arguments, for a legitimate purpose, I would try to put the arguments in a list instead of using a variable number of arguments. If someone else required me to use variable arguments, I would use varargs instead of the default behavior, and then only in the case where all the arguments are the same type.

Unspecified number of parameters in C functions - void foo()

I read here that in C void foo() means a function foo taking an unspecified number of arguments of unspecified type.
Can anyone give me or point me to an example where a C function takes an unspecified number of arguments? What can this be applied to in C? I couldn't find anything on the web.
That's an old-style function declaration.
This declaration:
void foo();
declares that foo is a function returning void that takes an unspecified but fixed number and type(s) of arguments. It doesn't mean that calls with arbitrary arguments are valid; it means that the compiler can't diagnose incorrect calls with the wrong number or type of arguments.
Somewhere, perhaps in another translation unit (source file), there has to be a definition of the function, perhaps:
void foo(x, y)
long x;
double *y;
{
/* ... */
}
This means that any call to foo that doesn't pass two arguments of type long and double* is invalid, and has undefined behavior.
Prior to the 1989 ANSI C standard, these were the only kind of function declaration and definition available in the language, and the burden of writing correct function calls was entirely on the programmer. ANSI C added prototypes, function declarations that specify the types of a function's parameters, which allow compile-time checking of function calls. (This feature was borrowed from early C++.) The modern equivalent of the above would be:
void foo(long x, double *y);
/* ... */
void foo(long x, double *y) {
/* ... */
}
Old-style (non-prototype) declarations and definitions are still legal, but they're officially obsolescent, which means that, in principle, they could be removed from a future version of the language -- though since they're still around in the 2011 standard I don't know that that will ever actually happen.
There is no good reason to use old-style function declarations and definitions in modern C code. (I've seen arguments for using them in some corner cases, but I find them unconvincing.)
C also supports variadic functions like printf, which do take an arbitrary number of arguments, but that's a distinct feature. A variadic function must be declared with a prototype, which includes a trailing , .... (Calling a variadic function with no visible prototype isn't illegal, but it has undefined behavior.) The function itself uses macros defined in <stdarg.h> to process its parameters. As with old-style function declarations, there is no compile-time checking for arguments corresponding to the , ... (though some compilers may check some calls; for example gcc warns if the arguments in a printf call are inconsistent with the format string).
This literally means that you are not telling the compiler what arguments the function takes, this means that it will not protect you from calling it with any arbitrary set of arguments. You would need to say in the definition precisely what arguments are actually taken for the function to be implemented however.
You could for example use this if you were generating a header file to describe a foreign function in external code, however you did not know what the function's signature actually was, it would still then be callable using your header but if you provide the wrong arguments in the call results are undefined.
The declaration void foo(); is not necessarily the same thing as a function that takes a variable number of arguments.
All that it is is a function declaration that indicates nothing about the number of arguments the function takes (actually, this is not exactly true, see below about argument promotions). The declaration isn't a function prototype, which provides information about the number and types of the parameters (using an ellipsis to indicate variable length parameters).
The function definition (where the body of the function is provided) might take a fixed number of arguments, and might even have a prototype.
When such a function declaration is used, it is up to the programmer making a call to foo() to get the arguments that foo() expects (and their types) correct - the compiler has no information about the argument list foo() requires. It also restricts the type of parameters that the function definition can use because when the function is called without a prototype, therefore the default argument promotions will be applied to the arguments at the function call. So a function that's declared without a prototype can only expected to get promoted arguments.
See the following C99 standard sections for some details:
6.7.5.3/14 "Function declarators (including prototypes)
...
The empty list in a function declarator that is not part of a
definition of that function specifies that no information about the
number or types of the parameters is supplied.
...
6.5.2.2 Function calls
...
If the expression that denotes the called function has a type that
does not include a prototype, the integer promotions are performed on
each argument, and arguments that have type float are promoted to
double. These are called the default argument promotions. If the
number of arguments does not equal the number of parameters, the
behavior is undefined. If the function is defined with a type that
includes a prototype, and either the prototype ends with an ellipsis
(, ...) or the types of the arguments after promotion are not
compatible with the types of the parameters, the behavior is
undefined. If the function is defined with a type that does not
include a prototype, and the types of the arguments after promotion
are not compatible with those of the parameters after promotion, the
behavior is undefined, except for the following cases:
one promoted type is a signed integer type, the other promoted type is the corresponding unsigned integer type, and the value is
representable in both types;
both types are pointers to qualified or unqualified versions of a character type or void.
The C function calling standard allows for a function to be called with zero or more arguments and the number of arguments may or may not match the function interface.
The way this works is that it is up to the caller to adjust the stack after the called function returns rather than the called function adjusting the stack unlike other standards such as Pascal which require the called function to manage the stack adjustment properly.
Because the caller knows what arguments and their types have been pushed onto the stack before the called function is called and the called function does not, it is up to the caller to clear the pushed arguments from the stack after the called function returns.
With updated C standards, the function call interface description has become more complex in order to allow the compiler to detect and report interface problems that the original K&R C standard allowed to go undetected by the compiler.
The standard now is that you specify variable argument lists using elipsis notation of three periods or dots after the last known and specified argument in the called functions interface specification or declaration.
So you would see something like the following for some of the Standard C Library I/O functions:
int sprintf (char *buffer, char *format, ...);
This indicates that the function sprintf requires that the first argument be a char pointer to a buffer, the second argument be a char pointer to a format string, and there may be other additional arguments. In this case any additional arguments would be what are needed to be inserted for the print format specifiers in the format string. If the format string is just a text string with no format specifies (something like %d for an integer for instance) then there would be no other arguments.
The newer C Standards specify a set of functions/macros for the use with variable argument lists, the varg functions. With these functions/macros the called function can step through the variable part of an argument list and process the arguments. These functions look something like the following:
int jFunc (int jj, char *form, ...)
{
va_list myArgs;
int argOne;
va_start (myArgs, form);
argOne = va_arg (myArgs, int);
va_end (myArgs);
return 0;
}
The problem that we have with variable argument lists is that C does not have a way of communicating the variable argument or even how many arguments. So the designer of the function has to provide a mechanism. In the case of the C Standard Library I/O functions this is done with the format that indicates the number of arguments following the format string by specifying format specifiers for each argument. And since there is nothing that does a consistency check, you can end up with a format string that specifies more or less than the actual arguments resulting in either garbage output or less output than expected.
Since modern C compilers have some degree of backwards compatibility for old C source code, that means that you can use some of the older constructs and the compiler will allow it though hopefully with a warning.
The new function interface specifications are designed to reduce the chances of using a function incorrectly. So the new standards recommend that you use the function interface declaration so that the compiler can help you by detecting interface problems and incorrect variable usage in the function call.
However if you want to be a risk taker you do not have to use this safety net so if you like you can just define a function with an empty argument list and wing it.
You might also find an answer I put into this question about currying in C that uses variable argument lists along with a way to determine how many arguments are provided.
As mentioned in many other answers, a function taking an unspecified number of arguments of unspecified type just means it's caller doesn't know about its definition. It's completely different from variadic functions where you must define with ... and then use va_list in stdarg.h to obtain the arguments
It's actually common in the past and there are many standard functions using that feature, for example open()/openat()/_open() with an optional last parameter
fd = open(filename, O_RDONLY);
fd = open(filename, O_CREAT | O_WRONLY, 0777);
See open() function parameters
main() is also a function that can receive varying number of arguments
int main();
int main(int argc, char **argv);
int main(int argc, char **argv, char **envp);
int main(int argc, char **argv, char **envp, char **apple);
In fact the Windows x64 calling convention is designed to support such unspecified number of arguments so it's a bit unfortunate for most modern usecases

Extremely simple C program won't compile in gcc compiler

I have the following program
main()
{
char a,b;
printf("will i get the job:");
scanf("%c",&a);
printf("%c",a);
printf("We did it");
}
I saved the file as Hope.c. When I try to compile the code above with the gcc compiler, I will get the following error:
Hope.c:In function 'main':
Hope.c:4:2:warning:incompatible implicit declaration of built-in function 'printf' [enabled by default]
Hope.c:5:2:warning:incompatible implicit declaration of built-in function scanf[enabled by default]
The compiler gives this error when I use printf() or scanf(), even in a simple "Hello world" program.
Is there something wrong with my code, or is there a problem with the compiler?
You're missing #include <stdio.h> at the top. Note that these were warnings, though, not errors. Your program should still have compiled as is.
Also, for good measure, you should write out the return type and parameters to main() and return a value at the end.
#include <stdio.h>
int main(void)
{
char a,b;
printf("will i get the job:");
scanf("%c",&a);
printf("%c",a);
printf("We did it");
return 0;
}
When you call functions that you're not familiar with, look at the man page and include the headers that are mentioned there. It's #include <stdio.h> in your case.
That's really extermely important, e.g. I have experienced printf( "%s", func( ) ) causing a segmentation fault although func() returned a valid null terminated string, but there was no prototype that declared the return type of func() as char * (doing a little bit research, we found that only the last four bytes of the 64 bit pointer have been passed to printf())
Yes, there's something wrong with the code. You're using the functions printf and scanf without declaring them.
The usual thing to do is use the declarations shipped with the compiler (because they're known to be correct) with
#include <stdio.h>
C.89/C.90 permits implicit declarations of functions. Your warning messages are informing you that you have not provided explicit declarations for scanf and printf. As has been mentioned, you can correct this by adding #include <stdio.h> to the beginning of your program. By not doing so, the behavior of your program is undefined.
Because scanf() and printf() have implicit declarations, they are treated as if their prototypes were given as:
extern int scanf ();
extern int printf ();
These declarations state that scanf() and printf() take an as of yet unknown number of arguments and return and int. However, this kind of declaration still assumes that these functions will take a fixed number of arguments. This is incompatible with their true prototypes, in which they take a variable number of arguments:
extern int scanf (const char *, ...);
extern int printf (const char *, ...);
Your C compiler apparently knows about the true prototypes of these functions because it treats those functions as "built-ins", meaning it can generate special case code when compiling to source code that calls those functions. Since the implicit declaration does not match its built-in knowledge of their prototypes, it generated the warning.
A compiler that did not have this "built-in knowledge" probably would not have generated the warning. It would then have generated code to call scanf() and printf() as if they took a fixed number of arguments. The error then may occur at runtime, since the calling convention for a function that takes a variable number of arguments may differ from the calling convention of a function that takes a fixed number of arguments.
This is all described in C.89 §3.3.2.2.
If the expression that precedes the parenthesized argument list in
a function call consists solely of an identifier, and if no
declaration is visible for this identifier, the identifier is
implicitly declared exactly as if, in the innermost block containing
the function call, the declaration
extern int identifier();
appeared.
...
If the expression that denotes the called function has a type that
does not include a prototype, the integral promotions are performed on
each argument and arguments that have type float are promoted to
double. ... If the function is defined with
a type that includes a prototype, and the types of the arguments after
promotion are not compatible with the types of the parameters, or if
the prototype ends with an ellipsis ( ", ..." ), the behavior is
undefined.
Note that C.99 removes the allowance for implicit function declarations.

Resources