0

I have this code that is supposed to find the smallest integer in an array. I am learning how to use pointers in C, and my code will not compile, but I do not know why. Rather than just the answer, I'd like to know why I am doing wrong or how is my thought process wrong.

I thought that *p_min will return the value inside the address.

The errors I get:

error: invalid type argument of ‘unary *’ (have ‘int’)

Warning: return makes pointer from integer without a cast

p is declared outside the function as int *p;

Code:

int *find_smallest(int a[], int N)
{
    int *p_min;

    for (p = &a[0]; p < &a[N]; p++)
    {
        if (*p[1] < *p[0]) {
            p_min = &p[1];
            return *p_min;
        } else {
            p_min = &p[0];
            return *p_min;
        }
    } 
}

3 Answers3

3

Not really sure what you're doing with the comparison logic. The most straightforward approach is to start with the first element, then check the rest sequentially, keeping the index of the smaller one. My code would be something like this:

int *find_smallest(int a[], int N)
{
    /* Make sure the input is valid */
    if (a && N > 0)
    {
        int i, N_min = 0;
        /* Check the rest of the elements */
        for (i = 1; i < N; i++)
        {
            /* If this one is lower, save the index */
            if (a[i] < a[N_min])
                N_min = i;
        }
        /* Return pointer to minimum */
        return a + N_min;
    }
    /* Return NULL to indicate an error */
    return NULL;
}
Yimin Rong
  • 1,890
  • 4
  • 31
  • 48
0
  • *p[1] < *p[0] should be *(p+1) < *p or p[1] < p[0].
  • The return type should be int.
  • You unconditionally return after one pass of the loop.
  • You never declared p.
  • Note that &a[i] can be written a+i.
  • You should be comparing p[0] (aka *p) and *p_min, not p[0] and p[1].
  • p[1] might even be beyond the end of the array!
  • You don't initialize p_min.
  • There's no reason to have int* p_min; instead of int min;.

Fixed:

int find_smallest(int a[], int N) {
    int min = a[0];  // Assumes a[] will have at least one element.
    for (int* p=a; p<a+N; ++p) {
        if (*p < min) min = *p;
    } 

    return min;
}

Or just:

int find_smallest(int a[], int N) {
    int min = a[0];  // Assumes a[] will have at least one element.
    for (int* p=a; N--; ++p) {
        if (*p < min) min = *p;
    } 

    return min;
}

Alternatively, one could use an index instead of a pointer.

int find_smallest(int a[], int N) {
    int min = a[0];  // Assumes a[] will have at least one element.
    for (int i=0; i<N; ++i) {
        if (a[i] < min) min = a[i];
    } 

    return min;
}

Or just:

int find_smallest(int a[], int N) {
    int min = a[0];  // Assumes a[] will have at least one element.
    for (int i=N; i--; ) {
        if (a[i] < min) min = a[i];
    } 

    return min;
}
ikegami
  • 367,544
  • 15
  • 269
  • 518
-4

There are lots of problems (and places to improve on) this code. It's very confusing, so I'm not entirely sure what you're trying to do, but I'll point out some places you should start.

  • Just a warning, if you want to modify the array, find_smallest(int a[], int N) will not do*, You need something like find_smallest(int (*a)[], int N);, which you would then access like (*a)[some_index].
  • Your function says it's returning a int *, but the two returns I see have int values.
  • Where is p declared?
  • Why do you need to use &a[0] instead of just a[0], if all you're doing is finding the smallest value in the array?
  • You keep trying to access *a[some_index]. It looks like you meant to pass it as I stated. Accessing it as *a[some_index] will result in all kinds of errors, you'll need to write something like (*a)[some_index]. That's how C recognizes pointers.
  • If either way you're returning *p_min, you shouldn't put the returns in the if-statements, as it'll just slow down the compiler and waste space.

* If you pass it like int a[], the function will only have a local copy of the variable, and will not be able to modify it. This'll result in a lot of confusing errors, so if you want to develop your function into anything bigger, this is something to consider.

MD XF
  • 7,860
  • 7
  • 40
  • 71
  • 2
    `int a[]` is perfectly equivalent to `int *a` as a function parameter, no copy of the array involved. Also, I'm not sure `int (*a)[]` is valid, IIRC that should be `int (*a)[*]`. – Quentin Feb 15 '17 at 18:48
  • JFYI: `int a[]` is [basically the same thing](http://stackoverflow.com/a/1641963/223424) as `int * a`, just a different syntax for access. – 9000 Feb 15 '17 at 18:49
  • @9000 Where did I say he should use `int *a` instead of `int a[]`? I stated that if he wanted to modify the array he should use `int (*a)[]`. – MD XF Feb 15 '17 at 18:50
  • Thank you! this is what I was looking for. p is declared as int *p; in the whole program, I edited that earlier. Sorry I am having confusions because I wasn't taught any of what you mentioned, but I really appreciate your input. It will help me improve. @MDXF – Diego Fabiano Feb 15 '17 at 18:51
  • @MDXF fair enough, I'll trust you that it's no compiler extension. But the point stands that you do not need a pointer to an array to modify the array's elements -- the array implicitly decays to a pointer already. – Quentin Feb 15 '17 at 18:51
  • @Quentin If you want to modify the local copy, absolutely, `int *a` is fine. But if you're actually looking to modify another function's array, `int (*a)[]` or something of the sort is necessary. – MD XF Feb 15 '17 at 18:52
  • I do not want to modify the array the whole thing of the function is just to find the smallest number in the array. @MDXF – Diego Fabiano Feb 15 '17 at 18:53
  • @DiegoFabiano The way you were accessing the array in the function made it seem like you wanted a pointer-to-array, and it's mainly just a helpful tip for the future, in case it ever needs to goes down that road. – MD XF Feb 15 '17 at 18:54
  • 2
    Re *Just a warning, if you want to modify the array, find_smallest(int a[], int N) will not do*, You need something like find_smallest(int (*a)[], int N);, which you would then access like (*a)[some_index].*", That's not true (`void foo(int a[]) { a[0] = 345; } int main() { int a[] = {123}; foo(a); printf("%d\n", a[0]); return 0; }`) and it's totally irrelevant to the question at hand. – ikegami Feb 15 '17 at 18:57
  • Re "*Why do you need to use &a[0] instead of just a[0]*", Because they wants a pointer to the first element of the array. – ikegami Feb 15 '17 at 18:57
  • @ikegami **Re comment #2** No, they don't want that, but that's what they're doing anyway, because they think that's what they want. **Re comment #1** It's not totally irrelevant, it's good advice for pointer manipulation. All right, so some of the time it works to simply pass `int a[]`, but it's safer to use the method I stated. **Re downvote** If you downvoted my answer because a) you answered too or b) you didn't like *one* of my points, sure, be a douchebag, but I can do the same to you, since your 5th point is 'totally irrelevant'. – MD XF Feb 15 '17 at 19:01
  • Re "*No, they don't want that, but that's what they're doing anyway*", No so. Your recommended `p = a[0];` is a type error. It's needs to be `p = &a[0]` (as the OP had), or just `p = a;`. This is about the only thing in the OP's code that was correct! /// Re "*it's good advice for pointer manipulation*", That doesn't contradict what I said. /// I downvoted your answer because of the bad information therein. As always, I'll retract the vote once the issues are addressed. The only douche is you for downvoting an answers because its author pointed out serious problems with yours. – ikegami Feb 15 '17 at 19:12
  • @ikegami I never suggested that they use `p = a[0]`, I suggested that they only access `a[0]` since there's no need to access `&a[0]`, which may have strange behavior anyway. /// I downvoted your answer because of the useless/unnecessary information within. /// "serious" problems? The only "serious problems" with this answer are the comments from you under it. – MD XF Feb 15 '17 at 22:49
  • There's no way in which `a[0]` can be used to access the elements of `a`. `p=&a[0]`, `p=a` and `a[i]` are all fine. But not `a[0]`. // you also still have that nonsense about needing `find_smallest(int (*a)[], int N)` to change the array. Run the program I posted in the earlier content to prove your statement wrong – ikegami Feb 16 '17 at 00:03
  • @ikegami [chat](http://chat.stackoverflow.com/rooms/135817/discussion-between-md-xf-and-ikegami). – MD XF Feb 16 '17 at 17:47