-1

I'm pretty new to coding and stumbled upon this issue when trying to code a program that prints the biggest number in an array.

Basically, if I don't include cout<<i;, the printf() will print the array location instead of the number 20. Any ideas why? (I'm guessing it is something stupid I overlooked, so sorry in advance).

#include <iostream>
using namespace std;

int maxinlst(int lst[], int size) {
    int maxNum;
    for (int i = 0; i < size; i++) {
        cout << i;
        if (lst[i] == lst[0])
            int maxNum = lst[i];

        else if (maxNum < lst[i]) {
            maxNum = lst[i];
        }
    }

    return maxNum;
}

int main() {
    int lst[] = {-19, -3, 20, -1, 5, -25};

    printf("%i", maxinlst(lst, 6));
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 4
    Turn on your compiler warning and see if there's anything suspicious (Hint: a redundant `int`). – iBug May 14 '21 at 02:08
  • The answers below solves the problem, but also notice that it's not a good idea to mix the use of `printf` and `cout`. The program will behave strangely if `std::ios::sync_with_stdio` is false and `printf` and `cout` are used together. – NemoYuan2008 May 14 '21 at 02:22
  • thanks @NemoYuan2008 will note that for the future! – Andrew Blackburn May 14 '21 at 02:29
  • @iBug Haha I can't believe I missed that but at least it helped me realize that I didn't have all warnings on. Thanks! – Andrew Blackburn May 14 '21 at 02:30
  • @NemoYuan2008 — there is no problem with interactions between the C++ streams and C-style I/O in this code. C++ streams are designed to work well with C-style I/O. Yes, you can deliberately mess with synchronization, but this code doesn’t do that. Please don’t spread FUD. – Pete Becker May 14 '21 at 02:31

2 Answers2

1

You shadow maxInt by declaring another variable with the same name. See my comments here:

int maxinlst(int lst[], int size) {
    // First declaration
    int maxNum;
    for (int i = 0; i < size; i++) {
        cout << i;
        if (lst[i] == lst[0])
            // Second declaration
            int maxNum = lst[i];

        else if (maxNum < lst[i]) {
            maxNum = lst[i];
        }
    }

    return maxNum;
}

This is legal in C++, and in most languages with block scope. The second declaration creates a new variable, but it's never used because it goes out of scope immediately, so the whole assignment, along with the conditional, can be eliminated by the compiler. If you enable compiler warnings, you should get a warning about the second declaration because that variable is never used again:

test.cpp: In function ‘int maxinlst(int*, int)’:
test.cpp:8:17: error: unused variable ‘maxNum’ [-Werror=unused-variable]
             int maxNum = lst[i];
                 ^~~~~~

This also means that the value of the outer maxNum after the first iteration of the loop is indeterminate and reading it could be undefined behavior so the second loop iteration is either going to (a) use an indeterminate value since the outer maxNum was never assigned or (b) something else entirely because of UB.

If the second conditional is never true (assuming an indeterminate value and not UB) then the value returned by this function will also be indeterminate -- whatever unpredictable number maxNum happened to be.

The correction here would be to remove int in the second declaration.

You could also rewrite this to avoid the first in-loop conditional:

int maxinlst(int lst[], int size) {
    // First declaration
    int maxNum = lst[0];
    for (int i = 1; i < size; i++) {
        if (maxNum < lst[i]) {
            maxNum = lst[i];
        }
    }

    return maxNum;
}

As far as why cout << i changes the value you see, that's exactly the nature of using indeterminate values / undefined behavior. You can't reason about what's happening. Adding or removing other code could also change the value returned by the function. You may even see different values if you run the program multiple times without making any changes to it.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • Thanks a bunch! What a stupid mistake haha. And thanks for the tips on the code and warnings, I really appreciate it! I'll look up how to enable warnings on CodeBlocks as well. – Andrew Blackburn May 14 '21 at 02:14
  • Welcome to Stack Overflow! [What should I do when someone answers my question?](https://stackoverflow.com/help/someone-answers) – MarianD May 14 '21 at 02:14
  • @AndrewBlackburn We all make dumb mistakes! I've been doing this kind of work for over 25 years and I *still* make at least one stupid mistake every day. So do my coworkers. At some point your attitude will shift from "dang, I made a mistake, better fix it quick before anyone notices" to "hey guys, come check out the stupid thing I did!" Eventually you realize we _all_ do this kind of crap and just laugh at it, and move on. – cdhowie May 14 '21 at 02:18
  • 1
    We may also mention the `std::max_element` from STL – prehistoricpenguin May 14 '21 at 02:21
0

You actually have two variables called maxNum. Inside your if statement, int maxNum = lst[i] defines a new variable called maxNum which hides the outer maxNum variable. The inner, newly defined maxNum is destroyed as soon as the program exits the if statement.

What makes you think that the array location is being print?

maxNum is not set to a particular value when it is defined. Because of that it's just going to have whatever was stored in the memory before.

If that value in memory is large, then maxNum will be larger than all the values in your array, then maxNum will never change and it will keep the garbage value.

So, when you get to your printf statement, the garbage value will be output. I doubt that the location of the array is being output. I bet that it's just whatever garbage was in memory.

brandon_busby
  • 122
  • 11