What are the different ways to call a function? - c

What are the different ways to call a function? For example, can I call a function without ()?

You can call by name:
function_name(args);
You can call by function pointer:
void (*function_pointer)(int, char *) = ...;
(*function_pointer)(3, "moo"); // classic function pointer syntax
function_pointer(3, "moo"); // alternate syntax which obscures that it's using a function pointer
No, you cannot call a function without using (). You can hide the () by using a macro but that just hides where they are; in the end you must use () somewhere.

You can use a macro:
#define f func()
but this is not a recommended way. Your code will be very difficult to read and understand.

In C the () is the function invocation syntax. You cannot call a function without it.

There are several pedantic ways to invoke a function without using (). Naming the function "main" (with correct parameter & return types) is one good way. You could register it as an interrupt handler. You could trick the compiler into jumping into it by smashing the stack (not portable and not recommended, works with gcc on 64-bit x86):
#include <stdio.h>
void foo()
{
printf("In foo\n");
}
void bar()
{
long long a;
long long *b = &a;
void (*fooptr)() = &foo;
b[2] = (long long)fooptr;
}
int main()
{
bar();
}

Related

why can not malloc in global but can use inline function for malloc [duplicate]

This question already has answers here:
Error "initializer element is not constant" when trying to initialize variable with const
(8 answers)
Closed 2 years ago.
Hi i have a test code for calling malloc as below:
#include <stdio.h>
#include <stdlib.h>
int *p;// = (int*)malloc(sizeof(int));
int main() {
//...
}
Of course this code will be fail when compile with the error: initializer element is not constant and i have referenced this question: Malloc function (dynamic memory allocation) resulting in an error when it is used globally. They said that we have to use malloc() in side a function. But if i change my code to:
#include <stdio.h>
#include <stdlib.h>
int *p;
static int inline test_inline(int *x) {
printf("in inline function \n");
x = (int*)malloc(sizeof(int));
return x;
}
test_inline(p);
int main(){
//...
}
As the definition of inline function: "Inline Function are those function whose definitions are small and be substituted at the place where its function call is happened. Function substitution is totally compiler choice." So this mean we can substitute the inline function test_inline in above example with the code inside it and it means we have call malloc() in global ? Question 1: is this wrong about inline or malloc() ?
Question 2: In the link i give about malloc function dynamic there is an answer said that "Not only malloc, u can't call any function as you have called here. you can only declare function as global or local there" but i see that we still can call function in global and in global we can initialization not only declaration as below:
#include <stdio.h>
#include <stdlib.h>
int b;
b = 1;
int test() {
printf("hello");
}
test();
int main() {
//...
}
So this mean in the global we still can declaration and initialization and call function. But when we compile the above code it has a warning that warning: data definition has no type or storage class So why we have this warning with variable b ? I do not see any thing which inconsequential here. And with the line test(); i have call a function outside main(), i know this make no sense because we never run test() but i have no problem, stil build success. So back to question 1 about the malloc(), i think with the answer that "we can not call a function in global or can not initialize", i think it is not true. Is there any explain more reasonable?
Please refer to the comments.
#include <stdio.h>
#include <stdlib.h>
int b;
b = 1; //this is only allowed, because the previous line is a tentative definition. [1]
int test() {
printf("hello");
}
test(); // this is taken as a function declaration, not a function call [2]
int main() {
//...
}
Case [1]:
Change you code to
int b = 5; // not a tentative defintion.
b = 1; // this assignment is not valid in file scope.
you'll see an error.
Case [2]:
If the signature of the function differs, you'll again see an error. Example: try the below:
float test( int x ) {
printf("hello");
return 0.5;
} //return changed to float, accepts an int as paramater.
test(); //defaults to int and no parameter - conflict!!
this will produce the error for conflicting types.
So, bottom line, no assignment, function call - all in all, no code that needs to execute at runtime, can be put into file scope. The reason behind that being, unless it's contained in a function that's called from main(), there's no way to know when / how to execute it.
You're not calling functions "globally".
Taking your example:
#include <stdio.h>
#include <stdlib.h>
int b;
b = 1;
int test() {
printf("hello");
}
test();
int main() {
//...
}
In C types default to int.
So the lines
int b;
b = 1;
are basically
int b;
int b = 1;
and the lines
int test() {
printf("hello");
}
test();
are just
int test() {
printf("hello");
}
int test(); // -> this is just a matching declaration
Have a look at:
https://godbolt.org/z/3UMQAr
(try changing int test() { ... to char test() { ... and you get a compiler error telling you that those types don't match)
That said, you can't call functions there. Functions are called at runtime by your program (especially malloc, which is asking your OS to allocate memory for you). I'm not a C expert here but as far as I know C doesn't have constexpr functions, which would be the only "exception".
See: Compile-Time Function Execution
Question 1: is this wrong about inline or malloc()
kind of: malloc does have to be called in a function, but the variable it works on can be declared global. i.e. int *pointer = NULL;//global scope
then pointer = malloc(someByteCount);//called within function. Now, pointer is still global, but also has a memory address pointing to someByteCount bytes of memory.
Question 2: In C, all functions are defined on the same level of a .c file, just like main(void){...return 0}, but all functions (except main(void)) must be called within the {...} of other functions, so in short, functions cannot be called from global space.
Illustration for Q2:
//prototypes
void func1(void);
void func2(void);
void func3(void);
int main(){
int val = test_inline(p);//...
}
int main(void)
{
//legal
func1();
func2();
func3();
return 0;
}
//not legal
func1();
func2();
func3();
//definitions
void func1(void)
{
return 0;
}
void func2(void)
{
return 0;
}
void func3(void)
{
return 0;
}
Errors in syntax of your example (see comments):
int *p = NULL;//initialize before use
static int inline test_inline(int *x) {
printf("in inline function \n");
x = (int*)malloc(sizeof(int));
printf("%p\n", x);
return 0;
//return x;//function returns int, not int *
}
//... test_inline(p);//must be called in a function
int main(void){
int val = test_inline(p);//function declaration returns int, not pointer
return 0;
}
This code compiles, and runs, but as noted in comments, usefulness may be lacking.
Question 1: is this wrong about inline or malloc() ?
Neither. Your understanding of inline is incorrect. The function call may be replaced with an inline expansion of the function definition. First, let's fix the function definition because the return type int doesn't match the type of what you're actually returning:
static inline int *test_inline( int *x )
{
printf( "in inline function\n" );
x = malloc( sizeof *x );
return x; // x has type int *, so the return type of the function needs to be int *
}
If you call this function like so:
int main( void )
{
int *foo = test_inline( foo );
...
}
what the compiler may do is substitute the function call with the assembly language equivalent of the following:
int main( void )
{
int *foo;
do
{
printf( "in inline function\n" );
int *x = malloc( sizeof *x );
foo = x;
} while( 0 );
...
}
Nothing's happening "globally" here. The substitution is at the point of execution (within the body of the main function), not at the point of definition.
Question 2: In the link i give about malloc function dynamic there is an answer said that "Not only malloc, u can't call any function as you have called here. you can only declare function as global or local there" but i see that we still can call function in global and in global we can initialization not only declaration as below:
In the code
int test() {
printf("hello");
}
test();
the line test(); is not a function call - it's a (redundant and unnecessary) declaration. It does not execute the function.
Here are some excerpts from the language definition to clarify some of this:
6.2.4 Storage durations of objects
...
3 An object whose identifier is declared without the storage-class specifier
_Thread_local, and either with external or internal linkage or with the storage-class
specifier static, has static storage duration. Its lifetime is the entire execution of the
program and its stored value is initialized only once, prior to program startup.
Bold added. Any variable declared outside the body of a function (such as p in your first code snippet) has static storage duration. Since such objects are initialized before runtime, they cannot be initialized with a runtime value (such as the result of a function call).
6.7.4 Function specifiers
...
6 A function declared with an inline function specifier is an inline function. Making a
function an inline function suggests that calls to the function be as fast as possible.138)
The extent to which such suggestions are effective is implementation-defined.139)
138) By using, for example, an alternative to the usual function call mechanism, such as ‘‘inline
substitution’’. Inline substitution is not textual substitution, nor does it create a new function.
Therefore, for example, the expansion of a macro used within the body of the function uses the
definition it had at the point the function body appears, and not where the function is called; and
identifiers refer to the declarations in scope where the body occurs. Likewise, the function has a
single address, regardless of the number of inline definitions that occur in addition to the external
definition.
139) For example, an implementation might never perform inline substitution, or might only perform inline
substitutions to calls in the scope of an inline declaration
All this means is that the inlined code behaves like it was still a single function definition, even if it's expanded in multiple places throughout the program.

Why does the function call work even though it is not defined before the call?

I have done this quiz, and do not understand the output
#include <stdio.h>
int main()
{
void demo();
void (*fun)();
fun = demo;
(*fun)();
fun();
return 0;
}
void demo()
{
printf("GeeksQuiz ");
}
Expected: Compiler error because I thought that normally demo() would need to be initialized before the call in main()?
Actual results: GeeksQuiz GeeksQuiz
Is my assumption wrong that functions generally need to be defined before they can be called?
functions generally need to be defined before they can be called
Well, not actually, compiler just needs to see a prototype before the call (usage). A forward declaration would be enough.
In your case, inside main(),
void demo();
is serving that purpose. Note that, this is not a function call.

Returning directly to main from a function call of a function call

just as a disclaimer this question has to do with a particular assignment I have an I am not asking for anyone to do my homework for me.
So basically I am supposed to implement a way to return directly to main from a function call of a function call.
Part of the stipulations are that we cannot use an assembly language instructions, gcc's asm(), or gcc built ins. After doing a lot of research on this on google I couldn't really find any examples to look at or even the source code for setjmp/longjmp (the purpose of this assignment is to copy those functionalities). I've asked some more older CS students for advice and most couldn't help or told me they are pretty sure it is not possible with the stipulations given. Any advice or pointers (haha) will be appreciated. Even a nudge in the right direction or confirmation that the assignment is not as complicated as I think will be greatly appreciated!
So far my best attempt:
-Use a setjmp function to store the address of where we left off in main (so something like x = foo1(); and pass x into setjmp(x)) and then have foo2 call my longjmp function where in longjmp I'll have the function set a pointer (*p) to my argument and then (*p-1) = address of x in main.
This didn't work but I thought it was the right idea trying change the return address in the call stack since if I understood it correctly, the arguments of the function are directly on top of the return address in the stack.
Here is the code I wrote:
int setjmp(int v);
int longjmp(int v);
int fun1(void);
int fun2(void);
int *add; //using global, not sure if best idea
int main(void)
{
int x = setjmp(x);
foo1();
return 0;
}
int setjmp(int v)
{
add = &v; //used a global variable
return 0;
}
int longjmp(int v)
{
int *p; //pointer
p = &v; //save argument address
*(p-1) = *add; //return address = address in main
return 1;
}
int foo1(void)
{
printf("hi1");
foo2();
printf("hi2");
return 0;
}
int foo2(void)
{
int a;
longjmp(a);
return 0;
}//output SHOULD be "hi1"
//output is currently "hi1" "hi2"
for what it's worth every line I have not commented was given as a skeleton and I cannot change it.
Excuse me in advance if something is off, I am quite new to C. Thank you.
"So basically I am supposed to implement a way to return directly to main from a function call of a function call. "
This requirement is nonsense. Any attempt to sate that requirement will result in trash code. Training to write things like this is directly harmful practice. This is a very bad assignment and your teacher should be ashamed for teaching you bad practice with no disclaimer. There is also never a reason to do things like this in real-world programs.
You can't implement the setjmp/longjmp functions in pure C, you would have to use inline assembler. They save the program counter and other such things needed by the specific system. They also meddle with the stack pointer, which is one reason they are dangerous.
So the only way to do this in standard C is to use the standard library functions setjmp/longjmp from setjmp.h. These are widely considered very bad and dangerous since they lead to unreadable spaghetti programming and many forms of undefined behavior. One example of undefined behavior from the C standard:
After a longjmp, there is an attempt to access the value of an object of automatic
storage duration that does not have volatile-qualified type, local to the function
containing the invocation of the corresponding setjmp macro, that was changed
between the setjmp invocation and longjmp call
Don't use these functions ever.
That being said, this is how you write horrible, dangerous programs:
// BAD! NEVER WRITE SPAGHETTI CODE LIKE THIS!
#include <stdio.h>
#include <setjmp.h>
#include <stdbool.h>
static jmp_buf jmp_main;
void func2 (bool one_more_time)
{
puts(__func__);
if(one_more_time)
{
longjmp(jmp_main, !one_more_time);
}
printf("end of "); puts(__func__);
}
void func1 (bool one_more_time)
{
puts(__func__);
func2(one_more_time);
printf("end of "); puts(__func__);
}
int main (void)
{
bool one_more_time = (bool)!setjmp(jmp_main);
puts(__func__);
func1(one_more_time);
printf("end of "); puts(__func__);
}
Output:
main
func1
func2
main
func1
func2
end of func2
end of func1
end of main
I don't think problem is that complicated. You should be calling another function with a condition on returning value such that if it is certain value (say 0) then return otherwise continue on the function.
So you can just replace foo2(); with :
if (foo2() == 0) return 0;
Now in foo2() function return 0; whenever you wish to return to main function call of foo1() otherwise continue with foo1() statements. You need not use setjmp here.
You may also find this article helpful: Tread programming examples

Declaring a function?

in C I am writing some of my very first exercises. Earlier on, I tried to declare a simple function inside of main and it comes with an error: "function definition is not allowed here". But I thought a function could be declared inside of main or outside, the only difference being the scope?? I have also read, in here, of other people writing functions inside of main, so why won't it let me do it?
thanks
You can declare a function inside another function:
int main(void) {
int foo(int); // declaration
...
}
But you can't define a function inside another function:
int main(void) {
// Doesn't work.
int foo(int x) {
return x * 2;
}
...
}
Also, declaring functions inside other functions is a really unusual thing to do, and essentially never necessary.

In C: sending func pointers, calling the func with it, playing with EIP, jmp_buf and longjmp

I need to make sure i understand some basic stuff first:
how do i pass function A as a parameter to function B?
how do i call function A from inside B ?
Now for the big whammy:
I'm trying to do something along the lines of this:
jmp_buf buf;
buf.__jmpbuf[JB_PC] = functionA;
longjmp(buf,10);
Meaning that I want to use longjmp in order to go to a function. How should I do it?
You need to use a pointer to a function. The syntax for declaring a function pointer is:
rettype (*)(paramtype1,paramtype2,...,paramtypeN)
So, for example, we might have the following code:
char functionA(int x)
{
printf("%d\n",x):
return 'a';
}
char functionB(char (*f)(int), int val)
{
return f(val); // invokes the function pointer
}
int main(int argc, char* argv[])
{
char result = functionB(&functionA,3); // prints "3"
printf("%c\n",result); // prints 'a'
return 0;
}
Also, a side note, that while &functionA takes the address of functionA, it is actually not necessary to use the ampersand there... I personally do it, since I think it makes it more clear that it is a function pointer. You invoke a function pointer using the same syntax that you would when invoking a function.
As for using jump buffers, I believe what you are doing is not something that can be relied upon. If you want to create a jump buffer and invoke setjmp before invoking some function, then later invoke longjmp so that you return to immediately prior to the call, then that is well-defined. The actual definition and structure of jmp_buf, though, is implementation-specific. There are certain requirements that it has to meet (e.g. it has to be an array type, because setjmp has to be able to take it by value and yet modify it), but other than that, the specification for setjmp.h does not define the structure of jmp_buf. So, anything that attempts to manipulate jmp_buf directly is going to be specific to a particular platform.
Passing functionA as a parameter to functionB:
typedef void function_type(void);
void functionA(void)
{
printf("This is function A\n");
}
int main(int argc, char **argv)
{
functionB(&functionA);
return (0);
}
Calling function A from function B:
void functionB(function_type *func)
{
func();
}
Using longjmp() to go to a function. The best answer is "Don't do this" - there's almost always a better way to achieve the same aim. Can you explain the situation where you need this?

Resources