0

I just started learning C, and I came across this in one of the example given, I know this is a function prototype, but the concept I am yet to wrap my head around is the fact that does

void function(char *);

mean when I finally declare the function, it is going take an argument char pointer argument like so

void function(char *arg){}

?

Tijani
  • 133
  • 2
  • 3
  • 16
  • 1
    Succinctly, yes. What else could it mean? – Jonathan Leffler Jan 05 '20 at 09:04
  • Is the fact that you can omit parameter names in function prototypes confusing you or? – bool3max Jan 05 '20 at 09:06
  • 1
    Just wanted to mention a leftover from cicra 1970 C : Forcing the programmer to declare functions before using them allows the compiler to work in one pass (i.e. read the code only once). – H S Jan 05 '20 at 09:11
  • 1
    *"when I finally declare the function"* -- the second piece of code is a definition. A declaration contains only the function name, arguments and return type (no code); the first piece of code in the question is a declaration. – axiac Jan 05 '20 at 09:14
  • 1
    @E.N.D Incorrect. Such an enforcement didn't exist at that time. Implicit function declarations removed by C99 standard. It was valid even in C89 standard. – Lxer Lx Jan 05 '20 at 09:50
  • @E.N.D A one-pass compiler was certainly appreciable in 1970, but nowadays... – Déjà vu Jan 05 '20 at 09:57

4 Answers4

6

Just to answer the question you gave:

What does “void fatal(char *);” mean?

This is the prototype/declaration of the function fatal.fatal is a function, which takes a pointer to char as one and only argument.

void is the return type of the function, which in this case mean that the function does not return a value to its caller or if it does, the value returned is interpreted as invalid by the caller.


The prototype/declaration of the function fatal() is important for the compiler. In this way, primarily the compiler will get "known", how the function is later used in the following program but secondary also checks if there are any inconsistencies between the definition, declaration and the use of the function.


In C, You may omit a specific identifier for the pointer to char in the declaration of the function, but not in the definition. This a circumstance where C is different as C++; In C++ it is permissible to omit the identifier also in the definition. You can look at the respective phrases in the standards in this answer.

So in the definition of fatal in C you have to provide an identifier for the char pointer:

// Definition of function fatal().
void fatal(char *a)
{
    printf("The string of (a) is: %s\n",a);      
}

but you can omit this one in the declaration:

void fatal(char *);

Note: The identifier between the provided arguments, when calling the function and the parameters specified in the declaration of the function may vary, like:

// Declaration (Protoype) of function fatal().
void fatal(char* a);   // parameter a (pointer to char);

int main()
{
    char b[] = "Hello";        // Declaration and Initialization of array b.
    printf("Let´s use the function fatal to print what the string in b is   
            contained of!\n");
    fatal(b);                  // when given as argument to a function, b 
                               // is a pointer to the first element of the char 
                               // array of b.
}

// Definition of function fatal().
void fatal(char* a)
{
    printf("The string of (a) is: %s\n",a);      
}

See more about the difference between parameters and arguments here: What's the difference between an argument and a parameter?


In the more far view, there is also an important difference between "pass by value" and "pass by reference". A pointer argument/parameter is always a pass by reference. What these two especially are and how they distinct is best explained here: What's the difference between passing by reference vs. passing by value?

In this context and the context of scope visibility, it is also important to know if you have f.e. an identifier x which refers to an object in the function fatal, the same identifier of x can be used in the caller, and vice versa, to refer to a total different object in each scope. - Means, you can have the same identifier (name) for different objects in different scopes but each identifier can only used once in its scope.

  • 1
    Thank you for the elaborate explanation :-) – Tijani Jan 05 '20 at 12:40
  • Things will become clearer by time and the more you use them. ;-) I´ve added a link to what "pass by reference" and "pass by value is". You should take a look at that topic too, even if it is not necessarily needed for the provided question, but it is related. – RobertS supports Monica Cellio Jan 05 '20 at 12:54
2

Here void function(char *); is a function prototype which is simply the declaration of a function that specifies function's name, parameters and return type. It doesn't contain function body.

It gives information to the compiler that the function may later be used in the program.

It is not needed if the user-defined function is defined before the main() function.

Himanshu Singh
  • 2,117
  • 1
  • 5
  • 15
1

does [...] mean when I finally declare the function, it is going take an argument char pointer argument [...] ?

Yes, it does.

The important thing with the declaration of the function are the parameters' types. The parameters' names are not needed within the declaration

void function(char *);

but only within the function's definition

void function(char *arg)
{
}

.

alk
  • 69,737
  • 10
  • 105
  • 255
0

It just informs the compiler what type parameters functions takes and what is the return type of it.

int main()
{
    double x = foo(1,2);
}

void foo(double x)
{
   printf("%f", x);
}

in this compiler does not know what parameters of the function foo are and how to pass them properly. Return type is also unknown. The compiler will assume they are int - which is not the truth in this case

https://godbolt.org/z/J8juc4

0___________
  • 60,014
  • 4
  • 34
  • 74
  • 1
    In C99 and beyond, it is stricly an error to call `foo()` when there is no declaration or definition of `foo()` in scope. However, that declaration need not be a full prototype;. The modern C compiler in strictly conforming mode should not assume `foo()` returns an `int`. – Jonathan Leffler Jan 05 '20 at 09:10
  • @JonathanLeffler most of the beginners use default compiler options and it is not C99 and beyond. – 0___________ Jan 05 '20 at 09:13
  • 3
    GCC 5 and later uses C11 by default. – Jonathan Leffler Jan 05 '20 at 09:15
  • @JonathanLeffler and it compiles it without any problems. Warnings are usually ignored by people starting with it. https://godbolt.org/z/tAcaoP – 0___________ Jan 05 '20 at 09:16
  • That code invokes undefined behaviour in C89, and is a constraint violation in C99 (and beyond). – Lxer Lx Jan 05 '20 at 10:19
  • @LxerLx and if you ignore warnings (as beginners usually do), what does it mean for them? Only strange terms. My answer is intentionally simple. As in the school - you do not start from the imaginary numbers and differential equations. – 0___________ Jan 05 '20 at 10:31