4

I'm just trying to learn c and I'm stuck. I'm trying to create a program that can take an input of two numbers, together with an operator and print out the answer.

The notation is reversed polish notation. That is to say, the input 2 1 + should give the output 3, the input 2 1 * should give the output 2.

Later, I will expand it so that you can enter longer expressions in rpn with some stack based stuff but lets focus on the case with just two operands for now.

This is what I have done:

#include <stdio.h>

main()
{
    int number1;
    int number2;
    char operator;
    scanf("%d %d %c", &number1, &number2, &operator);
    printf("%d", calculate(number1, number2));
}

int calculate(int number1, int number2)
{
    return number1+number2;
}

This works at suspected and it writes out the sum of number1 and number2. However, when I try passing a character as an argument to the function calculate, like this

#include <stdio.h>

main()
{
    int number1;
    int number2;
    char operator;
    scanf("%d %d %c", &number1, &number2, &operator);
    printf("%d", calculate(number1, number2, operator));
}

int calculate(int number1, int number2, char operator)
{
    return number1+number2;
}

I get a compile error

rpn.c:12:5: error: conflicting types for ‘calculate’
rpn.c:13:1: note: an argument type that has a default promotion can’t match an empty parameter name list declaration
rpn.c:9:15: note: previous implicit declaration of ‘calculate’ was here

Is it not possible to pass a char as an argument in c? I don't understand why this isn't working when it works with int. I have googled on this a lot, but the questions usually only covers passing an array of chars as an argument, not a char.

Or am I doing this all wrong?

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
user1661303
  • 539
  • 1
  • 7
  • 20

4 Answers4

3

Put the calculate() function above the main() function. The compiler needs to know about the function before it can call it.

Alternatively you can forward-declare it above main by including this line before main():

int calculate(int number1, int number2, char operator);

It will also help to turn on warnings in your compiler. With GCC you can use -Wall.

T Percival
  • 8,526
  • 3
  • 43
  • 43
2

Since the compiler doesn't see the definition of calculate() before it's called, it has to create an implicit declaration of it and hope that the declaration is right. It turns out that it's not.

To fix this, either move the definition of calculate() up above main() where it's called, or alternatively provide a function prototype of calculate() to declare what the function looks like before it's called, before main():

int calculate(int number1, int number2, char operator);

Also be aware that if you use the identifier operator for your variables and use a C++ compiler to compile you're code you'll get an error, since operator is a C++ keyword.

AusCBloke
  • 18,014
  • 6
  • 40
  • 44
  • The solution for that last problem is simple: use a C compiler to compile C code. – Keith Thompson Sep 10 '12 at 22:15
  • @KeithThompson: Yeah good point, but I've seen a lot of people compile their C code with a C++ compiler. – AusCBloke Sep 10 '12 at 22:18
  • I still don't understand. Why does it work with int as arguments but not with two ints and a char? If it is that I haven't declared it yet, shouldnt I get an error message in that case too? – user1661303 Sep 10 '12 at 22:28
  • @user1661303: It has to do with the fact that in certain cases `char` is promoted to `int`, and without an explicit declaration the compiler wouldn't know whether it needs to perform this promotion. That's what the second line of the error is telling you. From that error it looks like the implicit declaration has an empty parameter list, which means that the number (and type) of arguments to that function is unspecified. It could be that the function is variadic, in which case a `char` argument would be promoted to an `int`. – AusCBloke Sep 10 '12 at 22:52
2

You have to tell the compiler about the prototype for the function calculate.

#include <stdio.h>

int calculate(int,int, char); // This is your prototype.
main()
{
    int number1;
    int number2;
    char operator;
    scanf("%d %d %c", &number1, &number2, &operator);
    printf("%d", calculate(number1, number2, operator));
}

int calculate(int number1, int number2, char operator)
{
    return number1+number2;
}
Ryhan
  • 1,815
  • 1
  • 18
  • 22
  • 3
    Note that parameter names are optional in a prototype (that's not part of a definition). In other words, you *can* write `int calculate(int, int, char);`, but you can also write `int calculate(int number1, int number2, char operator);`. IMHO, the more explicit form is better. – Keith Thompson Sep 10 '12 at 22:21
1

When the compilers sees your call to calculate, it hasn't yet seen a declaration of calculate.

For starters, add this line before your definition of main:

int calculate(int number1, int number2, char operator);

(Note the semicolon after the ).)

Without that pre-declaration, the call to calculate creates an implicit declaration at the call; that implicit declaration doesn't work the same way (for obscure historical reasons having to do with argument promotions and old-style function declarations; don't worry about the details). That's for the 1990 version of the language. Starting with the 1999 ISO C standard, such implicit function declarations don't even exist. Consider invoking your compiler so it complies to the C99 standard (or even C11 if it supports it). You appear to be using gcc; if so, gcc -std=c99 -pedantic -Wall -Wextra will generally give you more thorough diagnostics.

Some other improvements:

main() should be int main(void).

The format string "%d" should be "%d\n", so it prints a complete line.

(Of course you'll want calculate to pay attention to the value of operator, but what you have is a good start.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • Thanks everybody for the quick responses. I will try it out. I also wonder about this void functions being int. Isn't c designed to be small and as little footprint on memory as possible? Then why would it make sense to make all void functions return an int? Wouldnt that make the function using more memory than it needs? I'm using gcc, would it try to compile c++ keywords or am I safe? – user1661303 Sep 10 '12 at 22:37
  • @user1661303: No, `void` functions are not `int`. A function defined to return `void` doesn't return a result. A function defined to return `int` returns an `int` result. *Prior to the 1999 standard*, a function with no explicit type implicitly returns `int`, so `func();` and `int func();` are equivalent declarations. (Prior to the 1989/1990 standard, there was no `void` keyword.) The 1999 standard dropped this "implicit int" rule, so it's no longer legal to omit the type; if a function returns `int`, you have to say so explicitly. This has nothing to do with memory footprint. – Keith Thompson Sep 10 '12 at 22:41
  • So if I'm understanding this correctly, prior to the 1989 standard, you couldn't have a function that didnt return a value? Would this make the memory footprint larger since you would have to return an int, even if the function in itself didnt have the need to send a return value? Sorry for the newbe questions. – user1661303 Sep 10 '12 at 22:47
  • @user1661303: It depends on the implementation, particularly on function calling conventions. The overhead of a single `int` object for each function call is typically small enough that it's just not worth worrying about. (Note that before 1989 there was no formal standard for the language; the first edition of [K&R](http://en.wikipedia.org/wiki/The_C_Programming_Language) was the de facto standard.) – Keith Thompson Sep 10 '12 at 22:55