tags:

views:

619

answers:

5

I'm a beginner programmer and I'm learning my first language, C.

I'm learning mostly from Deitel and Deitel's C How to Program book, but also using example tasks and things from the university, however I am stuck on one.

I have a very very basic understanding of pointers - adding & in front of a variable makes it print an address and * uses a pointer to use the value stored at that address or such.

The piece of code I've written is for calculating the greatest (largest?) common denominator of two numbers and doesn't actually need or involve pointers at all. It uses two functions and the logic is all correct because it prints out the correct answer to the screen if I do it from the second function, rather than returning it to the main. This is where the problem lies.

When the second function returns the answer value, for some reason it returns what I can only assume is a pointer. I have no idea why it does this. I would be able to work with this and convert it to look up the value - however it seems to be a pointer local the second function and is written over. Nothing on the web that I could find or in my book gave me any idea how to solve the problem.

Thanks if you've read this far. I've rambled far too much.

Here is my code and output. Any help or pointers (excuse the pun) would be greatly appreciated. I know I could just have it print in the second function but I would prefer to know how and why it doesn't return the value like I would like it to.

Code

#include <stdio.h>
int greatestCD (int num1, int num2);

int main(void)
{
    int a=0, b=0;
    int result;
    printf("Please enter two numbers to calculate the greatest common denominator from\n");
    scanf("%d%d", &a, &b);
    result = greatestCD (a,b);
    printf("Using the correct in main way:\nThe greatest common denominator of %d and %d is %d\n",a,b, result);
}

int greatestCD (int num1 ,int num2)
{ 

    if (num2==0){
        printf("Using the cheaty in gcd function way:\nThe greatest common denominator is %d\n",num1);
        return num1;
    } else {
        greatestCD(num2,(num1%num2));
    }    
}

Output (using 12 and 15 - the answer should be 3)

C:\Users\Sam\Documents\C programs>gcd
Please enter two numbers to calculate the greatest common denominator from
12
15
Using the cheaty in gcd function way:
The greatest common denominator is 3
Using the correct in main way:
The greatest common denominator of 12 and 15 is 2293524

Such a simple solution from frankodwyer. It's tiny things like that I either can't spot or don't know about. So what was being returned wasn't a pointer and was just junk?

Thanks a million.

+2  A: 

You don't return anything from your function, so the value 2293524 is just random junk. Doesn't your compiler give you a warning about a missing return value?

erikkallen
+9  A: 

You are missing a 'return' statement in the last line of the function greatestCD()

greatestCD(num2,(num1%num2));

Make it

return greatestCD(num2,(num1%num2));

(you may still have further debugging to do, but this is why it's returning junk...you're not telling it what else to return)

edit: I'd also suggest that when compiling in future you turn on all compiler warnings...if you're using gcc then try adding the flag -Wall to your compile command. This should warn you when you're doing things that may lead to bugs like this. (Not every such warning is an error necessarily, hence 'warning', but it usually indicates a possible problem.)

frankodwyer
Thanks a bunch. So what was being returned was just junk and not a pointer at all ?
Sam Phelps
It very likely was a pointer, but it's just whatever was already in the return value location. For instance, on x86 the value you got was whatever the compiler happened to put in the eax register.
Cody Brocious
A: 

More strange thing is that the program works on my linux machine. A bug or feature of gcc?

/dev/shm $ gcc x.c
/dev/shm $ ./a.out
Please enter two numbers to calculate the greatest common denominator from
12
15
Using the cheaty in gcd function way:
The greatest common denominator is 3
Using the correct in main way:
The greatest common denominator of 12 and 15 is 3
/dev/shm $ gcc --version
gcc (Debian 4.3.2-1) 4.3.2
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
most likely the return value just happens to be in the right register at the time.
frankodwyer
I changed the code to test the version of gcd function missing return keyword against a corrected version, and for all i, j < 5000, the function works correctly.
It also worked correctly (with or without the missing return) on OSX using gcc.
joel.neely
Undefined behaviour permits a program to work correctly by accident. Do not rely on it - the behaviour is undefined, and GCC is not required to maintain consistency across releases and it could break whenever it wants. Any other compiler can do whatever it likes: search 'nasal demons' on Google.
Jonathan Leffler
+3  A: 

Since you're learning C, independent of your missing-return bug, here are some observations and advice:

  • Pointers are the most difficult feature of the language to learn, especially when you get into malloc() and free(). Don't get discouraged.

  • Throw away Deitel and Deitel and get yourself a copy of Kernighan and Ritchie. It's one of the best language books ever written.

  • Turn on all warnings, all the time. If you can use MacOS or Linux, gcc -Wall -Werror -O is pretty good.

  • Run every C program under valgrind. Valgrind is a wonderful tool that is designed to catch errors in the way you use pointers. It will save your bacon!

Good luck!

Norman Ramsey
Any particular reason you say to throw Deitel and Deitel away or is it just because The C Programming Language is THE book to have ?
Sam Phelps
Norman Ramsey
+1  A: 

See the question Should I Not Use a Herb Schildt Book to Learn From, and in particular the list referenced at http://www.cs.technion.ac.il/users/yechiel/CS/BadBooksC+C++.html. Although it lists the C++ book by Deitel and Deitel, there tends to be a strong family resemblance between books by a given pair of authors. I would be inclined to get yourself a good book on C. I learned from Kernighan & Ritchie (first edition, when there was only one edition), so I would recommend that - it is succinct and accurate (like C itself).

Jonathan Leffler
Sam Phelps