Couldn't implement function with variable arguments - c

I was trying to implement function with variable arguments but was getting garbage values as output.I have referred this article before trying to implement on my own.Could anyone help me out with this code as I am unable to understand what's wrong in this code.
/* va_arg example */
#include <stdio.h> /* printf */
int FindMax (int n, ...)
{
int i,val,largest,*p;
p=&n;
p+=sizeof(int);
largest=*p;
for (i=1;i<n-2;i++)
{
p+=sizeof(int);
val=*p;
largest=(largest>val)?largest:val;
}
return largest;
}
int main ()
{
int m;
m= FindMax (7,702,422,631,834,892,104,772);
printf ("The largest value is: %d\n",m);
return 0;
}

The problem is that you try to access locations on the stack directly where you assume to find your arguments. Calling conventions are machine- and sometimes compiler-specific and an implementation detail you can never rely on, so probably your arguments are not found on the stack where you assume they are. In terms of C, your code just invokes undefined behavior
Solution: use stdarg.h for accessing the arguments, that's what it's there for.
#include <stdio.h> /* printf */
#include <stdarg.h>
int FindMax (int n, ...)
{
va_list ap;
int i,val,largest;
va_start(ap, n); // <- ap is the argument pointer, this initializes it
// based on the last non-variadic argument.
largest=0;
while (n--)
{
val = va_arg(ap, int); // <- fetch argument and advance pointer
largest=(largest>val)?largest:val;
}
va_end(ap); // done with argument pointer
return largest;
}
int main ()
{
int m;
m= FindMax (7,702,422,631,834,892,104,772);
printf ("The largest value is: %d\n",m);
return 0;
}

Related

Why am I not able to access values that were stored in another function?

Basically, why does it not just print the integers that are entered. Right now it just prints garbage value, but I do not know why it cannot access the values stored after it leaves the function. It only seems to get messed up after leaving the getIntegersFromUser function. If I run the for loop in the getIntegers function it does it properly, but why not in the main function?
Thanks in advance for your help.
#include <stdio.h>
#include <stdlib.h>
void getIntegersFromUser(int N, int *userAnswers)
{
int i;
userAnswers =(int *)malloc(N*sizeof(int));
if (userAnswers)
{ printf("Please enter %d integers\n", N);
for (i=0;i<N; i++)
scanf("%d", (userAnswers+i));
}
}
int main()
{
int i, M=5;
int *p;
getIntegersFromUser(M, p);
for (i=0;i<5;i++)
printf ("%d\n", p[i]);
return 0;
}
Also, this is a homework question, but it's a "Bonus Question", so I'm not trying to "cheat" I just want to make sure I understand all the course material, but if you could still try to give a fairly thorough explanation so that I can actually learn the stuff that would be awesome.
Pointers are passed by value. The function is using a copy of your pointer, which is discarded when the function ends. The caller never sees this copy.
To fix it, you could return the pointer.
int *getIntegersFromUser(int N)
{
int *userAnswers = malloc(...);
...
return userAnswers;
}
/* caller: */
int *p = getIntegersFromUser(M);
Or you could pass your pointer by reference so the function is acting on the same pointer, not a copy.
void getIntegersFromUser(int N, int **userAnswers)
{
*userAnswers = (int *) malloc(N*sizeof(int));
...
}
/* caller: */
int *p;
getIntegersFromUser(N, &p);

All the functions in c are globally defined, then why we need to pass them to function as argument?

In c, we have to define all the functions globally. while studying function pointer i got some program where programmer passes function name as parameter to other function. so why we need to pass function to other function if they all are globally defined?
here i am giving small sample program :
#include<stdio.h>
void bsort(int arr[],int n,int (*compare)(int,int)) //bubble sort
{
int i,j,temp;
for(i=0;i<n;i++){
for(j=0;j<n-i-1;j++){
if(compare(arr[j],arr[j+1]) > 0 ){
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
int compare(int a,int b)
{
if(a > b) return 1;
return -1;
}
void main()
{
int i;
int arr[5]={6,5,1,9,2};
bsort(arr,5,compare);
for(i=0;i<5;i++)
printf("%d ",arr[i]);
}
in this code, if we remove 3rd argument in definition and calling part of bsort function then also our program will give us same output.so for function pointer this program doesn't make sense.
can you please do some modification in this code and make it good example for function pointer.
Thanks.
Your code does not actual need passing functions as parameters. But your example is rather didactic to make you understand how function pointers work.
However it's important to understand them as they might become very useful especially when dealing with libraries loaded at runtime. There are tons of examples where function pointers are really a good tool.
Here's one:
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
double doOperation(double arg, double (*func)(double))
{
return (*func)(arg);
}
int main(int argc, char **argv) {
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen ("/lib/libm.so.6", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
cosine = dlsym(handle, "cos");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
printf ("%f\n", doOperation(2.0, cosine);
dlclose(handle);
}
You open a library, search for the cosine function, and then pass it as an argument to doOperation.
You can also look here for more info.
Function pointers are used when you might need to change the behavior of your function call depending on some dynamic requirement.
This page sums it up short and sweet:
A function pointer is a variable that stores the address of a function that can later be called through that function pointer. This is useful because functions encapsulate behavior. For instance, every time you need a particular behavior such as drawing a line, instead of writing out a bunch of code, all you need to do is call the function. But sometimes you would like to choose different behaviors at different times in essentially the same piece of code.
A few excellent examples are available there are well.
You pass a function [pointer] to another function because you want to dynamically direct which function the receiver calls. Or more precisely, because the receiver function is built to allow you to do so, thereby requiring you to do so. The pointed-to function does not need to be available at the time the receiver is compiled.
The comparison function required as a qsort() argument is the prototypical example.
Q: Why pass a function to another function?
Without re-writing bsort(), code can sort more than 1 way by only changing the compare function.
#include <stdio.h>
#include <stdarg.h>
int compare_up(int a,int b) {
if(a > b) return 1;
return -1;
}
int compare_down(int a,int b) {
if(a < b) return 1; // reverse the compare
return -1;
}
int compare_random(int a,int b) {
return rand() & 1; // mix them up
}
int main(void) {
int i;
int arr[5]={6,5,1,9,2};
bsort(arr,5,compare_up);
for(i=0;i<5;i++) printf("%d ",arr[i]); puts("");
bsort(arr,5,compare_down);
for(i=0;i<5;i++) printf("%d ",arr[i]); puts("");
bsort(arr,5,compare_random);
for(i=0;i<5;i++) printf("%d ",arr[i]); puts("");
return 0;
}

C, variadic functions and stdarg.h

I found this code on the codegolf.stackexchange site.
#include <stdio.h>
#define function int
#define var int
struct { int (*log)(const char *,...); } console = { printf };
/* From here on only JavaScript! */
function fac(x){
if(x < 2) return 1;
return x * fac(x - 1);
}
function main(){
console.log("Hello world!\n");
for(var i = 0; i < 10; i++){
console.log("%i! = %i\n", i, fac(i));
}
return 0;
}
// *Should* we export the main function of this library??/
exports.main = main;
My question is, how is he able to run variadic function without including stdarg.h?
Because he is not manipulating the ... parameter, but simply passing pointer to a function which internally manipulates the ... parameter, which in the case is printf:
int __cdecl printf(const char *_Format, ...);
Note: not all compilers support the __cdecl calling convention.
Aswell, the macros he has defined are pointless and should not be used under any circumstance, as it is not C.

Undeclared identifier in C function

When I compile the following C function / program I get errors like "missing ';' before 'type' 'remainder' : undeclared identifier" - what is wrong with this function?
#include <stdio.h>
void conversionTo(int number,int base) {
if(number==0)
return;
int remainder=number%base;
conversionTo((number/base),base);
if(remainder<10)
printf("%c",'0'+remainder);
else
printf("%c",'a'-10+remainder);
}
int main() {
conversionTo(int number,int base);
return 0;
}
I'm not a C expert, but from experience very long ago I believe you cannot declare variables in the middle of a function.
Also, it's unclear what you are trying to do with the function / print statements.
Try this:
#include <stdio.h>
void conversionTo(int number,int base) {
int remainder=number%base;
if(number==0)
return;
conversionTo((number/base),base);
if(remainder<10)
printf("%c",'0'+ remainder); // Through the way ASCII works that gives the ASCII rep
// of the remainder.
else
printf("%c",'a'-10+remainder); // Hex digits (A-F).
}
int main() {
conversionTo(/*Any number here*/10, /*any base number here*/2);
return 0;
}
You need to defines variables, then they can be used.
So this:
int main() {
conversionTo(int number,int base);
return 0;
}
should become this:
int main(void)
{
int number;
int base:
number = 47;
base = 11;
conversionTo(number, base);
return 0;
}
Also non C99 compliant compilers do not like having variables declared in the middle of a context:
void conversionTo(int number,int base) {
if(number==0)
return;
int remainder=number%base; /* this would fail. */
conversionTo((number/base),base);
To get around this open another context:
void conversionTo(int number,int base) {
if(number==0)
return;
{
int remainder=number%base;
conversionTo((number/base),base);
if(remainder<10)
printf("%c",'0'+remainder);
else
printf("%c",'a'-10+remainder);
}
}
You have to invoke your function with a value or variable, not a declaration:
conversionTo(123, 10); // using constant value
or
int number = 123, base = 10; // variable declaration
conversionTo(number, base); // using variable
You are calling your function wrong - pass the arguments this way:
conversionTo(2,2); // assuming you want to convert 2 to binary
or
int number = 123, base = 10;
conversionTo(number, base); // note this is not the same number and base as in the definition of your conversionTo function
Full code:
#include <stdio.h>
void conversionTo(int number,int base)
{
if(number==0)
return;
int remainder=number%base;
conversionTo((number/base),base);
if(remainder<10)
printf("%c",'0'+remainder);
else
printf("%c",'a'-10+remainder);
}
int main()
{
conversionTo(2,2); // assuming you want to convert 2 to binary
return 0;
}
There are 3 things when using functions:
Function declaration / prototype - the prototype of your function is:
void conversionTo(int ,int );
Function definition:
void conversionTo(int number,int base /* Parameter list*/)
{
// your functionality
}
Function call where you pass your arguments to your function:
conversionTo(2,2);
The statement conversionTo(int number,int base); simply re-declares it. Try this even this will compile:
int main()
{
printf("Hello World");
int main();
}
conversionTo(int number, int base)
is the syntax for declaring which parameters the function can take. To actually call the function, you need to omit the type (assuming you have variables of the respective name)
int number = 5;
int base = 10;
conversionTo(number, base); // <-- no int here!
Or you can use numbers directly:
conversionTo(5, 10);
Your function definition number and base in your function declaration void conversionTo(int number, int base) are the names that the values passed to it will have inside the function. So, if you call conversionTo(2,5), 2 will be seen inside the function as number, while 5 will be seen as base.
If you want to use variables instead of contants to call the function, you could do that:
int main()
{
int base = 2;
int number = 5;
conversionTo(base, number);
return 0;
}
In this confusing example, the variables base and value have value 2 and 5, respectively. But as you pass them to the function, the values inside it will be number = 2 and base = 5. This shows that those variables are actually different, despite of having the same name.
You should compile with $CC -std=c99, to enable declaring variables in the middle of a block.
(see section 6.8 in the specification)
The declaration "int remainder" must come before any statements in a block.
A declaration may have an initializer as you have here.
You could do:
void conversionTo(int number,int base) {
if (number > 0) {
int remainder...
}
}
since the function will not work with negative numbers.
To fix the other bugs in the routine:
void conversionTo(int number,int base)
{
if(number>=0&&base>0&&base<=36)
{
int remainder=number%base;
number/=base;
if(number>0)conversionTo(number,base);
printf("%c",(remainder<10)?'0'+remainder:'a'+remainder-10);
}
}
This will print a 0 if number is zero and only recurse if needed.

What does "..." mean in a C function declaration?

What does this mean?
void message(int x, int y, ...)
I can't understand what ... is.
Can anybody explain?
... denotes a variable list of arguments that can be accessed through va_arg, va_end and va_start.
Unspecified/variable number of parameters. To handle such function you have to use the va_list type and va_start, va_arg, and va_end functions:
An example taken from here:
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
int maxof(int, ...) ;
void f(void);
main(){
f();
exit(EXIT SUCCESS);
}
int maxof(int n args, ...){
register int i;
int max, a;
va_list ap;
va_start(ap, n args);
max = va_arg(ap, int);
for(i = 2; i <= n_args; i++) {
if((a = va_arg(ap, int)) > max)
max = a;
}
va_end(ap);
return max;
}
void f(void) {
int i = 5;
int j[256];
j[42] = 24;
printf("%d\n",maxof(3, i, j[42], 0));
}
You can find more details here
You have defined a function message somewhere that takes at least two arguments of type int and then some optional arguments indicated by the "...". (printf is another function taking optional arguments).
The optional arguments can be accessed using the va_* functions.
... represents final argument passed as an array or as a sequence of arguments.
It's the variable argument formal parameter. From the syntactical prospective it allows you pass a variable number of parameters (at least two, which are x and y, but even more).

Resources