C, variadic functions and stdarg.h - c

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.

Related

A weird type of defining a function

I learning C for 1 years, i saw a type of defining a function. I couldn't name it, so i want to know the name of the defining function.
We defining functions as standard:
FunctionReturnType FunctionName(FunctionArgs)
{
codes();
}
But i saw that type:
FunctionReturnType FunctionName(FunctionArgs)(TheWeirdArea)
{
codes();
}
So what we doing for in i named as TheWeirdArea? I guess it's relative with function arguments, but i want to know correctly what we do in TheWeirdArea.
I guess this is about returning a function pointer to a function looking like
FunctionReturnType func(TheWeirdArea);
Here is an example:
#include <stdio.h>
int bar1(int b)
{
printf("bar1\n");
return 42 + b;
}
int bar2(int b)
{
printf("bar2\n");
return 100 + b;
}
int (*foo(int a))(int b) // Returns a function pointer
{
if (a == 1) return bar1;
return bar2;
}
int main(void) {
printf("%d\n", foo(1)(100));
printf("%d\n", foo(2)(200));
return 0;
}
Output:
bar1
142
bar2
300
Hope this dummy example help you
int add(int x,int y)
{
return x+y; //very dummy function return x+y
}
typedef int (*pointer_to_add)(int,int);
/* this is a declaration of function pointer works
with any function has an int return type and
accept two int arguments not only add */
int (*my_function(int arg1, double arg2))(int, int)
{
/*This a function accept an int argument
arg1 and double arg2 and return pointer to a function or address of function
which has a two int type arguments and return an int */
pointer_to_add ptr=add; //ptr is a pointer now to add function.
return ptr;
}
More simple form
pointer_to_add my_function(int arg1,double arg2)
{
pointer_to_add ptr=add;
return ptr;
}
Now in your main code you can use the returned address like:
int main(void)
{
pointer_to_add P=my_function(25,3.5);
printf("%i",p(22,33));
return 0;
}

Couldn't implement function with variable arguments

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;
}

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 function (without parameters) call with parameters

I'm wondering something like this is possible:
// declaration
void func();
int main()
{
int ar[] = { 1, 2, 3 };
func(ar); // call with parameter
return 1;
}
void func() // no parameters
{
// do something
}
Can someone explain me this and especially how can I access ar in func()?
In C (not C++), a function declared as func() is treated as having an unspecified number of untyped parameters. A function with no parameters should be explicitly declared as func(void).
A hack would be to exploit the GCC calling convention.
For x86, parameters are pushed into stack. Local variables are also in the stack.
So
void func()
{
int local_var;
int *ar;
uintptr_t *ptr = &local_var;
ptr += sizeof(int *);
ar = (int *)ptr;
May give you the array address in ar in x86.
For x86_64, the first parameter is stored in rdi register.
void func()
{
uintptr_t *ptr;
int *ar;
asm (
"movq %%rdi, %0"
:"=r"(*ptr)
:
:"rdi");
ar = (int *)ptr;
May give you the array address in ar in x86_64.
I have not tested these code myself and you may be to fine tune the offsets yourself.
But I am just showing one possible hack.
If you want to use any function with no parameters with any return type, it should be declared as (In C)
return_type func(void). It is only generic way of function declaration.
But any how, for your question , it possible to access but not generic..Try this program...
#include<stdio.h>
int *p;
void func();
int main()
{
int ar[] = { 1, 2, 3 };
p=ar;
printf("In main %d\n",ar[0]);
func(ar); // call with parameter
printf("In main %d\n",ar[0]);
return 1;
}
void func() // no parameters
{
printf("In func %d \n",*p);
*p=20;
}
Even this program works fine, it is not generic way and also is undefined.
if you declare function like void func (void) ,it will not work.
You can't access ar in func(), since you dont have a reference to it in func().
It would be possible if ar would be a global var or you have a pointer on it.
So that you can do something with func(), you need to pass it the input data you'll work with.
First you must declare the function properly :
// declaration
void func(int []);
The define it :
void func( int a[] )
{
// do something
printf ("a[0] = %d\n", a[0]);
}
Full code :
#include <stdio.h>
// declaration
void func(int []);
int main()
{
int ar[] = { 1, 2, 3 };
func(ar); // call with parameter
return 1;
}
void func( int a[] )
{
// do something
printf ("a[0] = %d\n", a[0]);
}
This will display :
a[0] = 1
You can implement something like this.
void func(int *p, int n);
int main()
{
int ar[] = { 1, 2, 3 };
func(ar, sizeof (ar)/sizeof(ar[0]) ); // call with parameter
return 1;
}
void func(int *p, int n) // added 2 parameters
{
int i=0;
for (i=0; i<n; ++i){
printf ("%d ", p[i]);
}
}

abstract function pointers

How would I create an array of ten function pointers? What I have is a for loop, and I want to set a function pointer to a different function on each iteration. so:
//pseudocode
for i (0..10)
function = array_of_functions[i];
//...
// Define alias for function pointer type for convenience
typedef void (*action)(int);
// Example function
void print(int) { ... }
action fs[10] = { print, ... };
for (int i = 0; i < 10; ++i)
{
action f = fs[i];
// Call it somehow
f(i * i);
}
This code:
return_t (*array_of_functions[10])(arg1_t, arg2_t);
Declares "array_of_functions" as a 10-element array of function pointers where each pointed-to function takes two arguments of type arg1_t and arg2_t and returns type return_t. Replace types and adjust the number of arguments as appropriate.
Any time you have to deal with ugly function pointer syntax it's better to use a typedef.
#include <iostream>
void a(int i)
{
std::cout<<"a: "<<i<<std::endl;
}
void b(int i)
{
std::cout<<"b: "<<i<<std::endl;
}
typedef void (*fn)(int);
int main(int argc, char**argv)
{
fn foo[2];
foo[0] = a;
foo[1] = b;
for(size_t i = 0; i < sizeof(foo) / sizeof(foo[0]); ++i)
{
foo[i](i);
}
return 0;
}
The simplest way to do it is to create a typedef for your function, and then declare an array with that type. To create a typedef for the function: typedef returntype (*typedefname)(argtype1,argtype2,...,argtypeN); EX:
#include <stdio.h>
#include <stdlib.h>
typedef void (*functype)();
void func1()
{
//...
}
void func2()
{
//..
}
//...
void func10()
{
//...
}
int main(int argc, char* argv[])
{
functype array[] =
{
&func1,
&func2,
&func3,
&func4,
&func5,
&func6,
&func7,
&func8,
&func9,
&func10
};
// Use the array...
return 0;
}
T (*array_of_functions[10])();
Where T is the return type of each function (all functions return the same type, naturally). Things get tricky if you want to store pointers to functions with different numbers/types of parameters:
int foo(void) {...}
int bar(int x) {...}
int bletch(double y, double z) {...}
...
int (*array_of_functions[10])() = {foo, bar, bletch, ...};
If so, you'll have to keep track of what number and types of parameters each function requires somehow so you can call it correctly.
I'm actually kind of down on typedefs for function pointer types; they tend to obscure as much as they simplify.

Resources