1

I was given the assignment of writing a C code which contains a function, which when passed through an array of length n returns a pointer to the array’s largest element. In order to make it easy for us, the length n was set to 10.

I wrote the code below and compiled it and it didn't show any error. Then, I ran this code and it asked for the 10 inputs for the array, but instead of returning the pointer with the largest element, it read segmentation fault 11.

I am new to pointers, and so could not figure out what exactly went wrong. Any help will be greatly appreciated.

#include<stdio.h>
#define N 10

int *find_largest(int a[], int n)
{
    int i;
    int *max;
    *max = a[0];

    for(i = 1; i < n; i++)
    {
        if(a[i] > *max)
            *max = a[i];
    }
    return max;
    // this function returns the pointer with the max. value                       
}

int main(void)
{
    int b[N], i;
    int *p;

    printf("Enter %d numbers: ", N);
    for(i = 0; i < N; i++)
        scanf("%d", &b[i]);
        //scans all the inputs                                                         

    p = find_largest(b, N);
    //p gets assigned the value of the max valued pointer                          

    printf("largest element: %d", *p);

    return 0;
}

Edit- After looking at the wonderful advices given, I modified my code a bit. I changed *max=a[0] to max= &a[0], and *max=a[i] to max=&a[i]. Now, the code runs without any error, but instead of returning the pointer with the largest value, it returns the largest input instead.
screenshot of what is happening

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
  • 2
    `*max = a[0];` -> `max = &a[0];` and similar elsewhere. – Yunnosch Apr 30 '18 at 06:01
  • 1
    @Mulliganaceous Signal number, not errno. – melpomene Apr 30 '18 at 06:03
  • A function can always return its own type. There is no need to declare `int *max;` simply `int max = INT_MIN;` will work and change the return type to `int find_largest(int a[], int n)`. – David C. Rankin Apr 30 '18 at 06:05
  • 1
    @DavidC.Rankin The assignment says the function needs to return a pointer. – melpomene Apr 30 '18 at 06:07
  • 1
    A function can always return its own type -- so I guess leaving it as `int *` would be just what the prof ordered here `:)` – David C. Rankin Apr 30 '18 at 06:16
  • If on the other hand, none of the answers actually helps you, then taking away the accepted is correct. In that case I am sure that all answerers welcome feedback, even if it is about a shortcoming. So please explain in which way all of the answers fail to help you. – Yunnosch Apr 30 '18 at 06:33
  • If your code, which changes as proposed in the answers, is returning not a pointer but a value, then please add a "Edit, changed code with answer-recommendations: ... code ... It now returns value instead of pointer." We need to see your code. What you describe seems unlikely. – Yunnosch Apr 30 '18 at 06:37
  • 1
    Compile with all warnings and debug info: `gcc -Wall -Wextra -g` with [GCC](http://gcc.gnu.org/). Then [use the `gdb` debugger](https://sourceware.org/gdb/current/onlinedocs/gdb/) to understand the faulty behavior of your program – Basile Starynkevitch Apr 30 '18 at 06:40
  • Without seeing the *full* adjusted code, it's hard to judge what's currently really wrong, after your updates. Does it *return* the largest (maximum) input, or just *prints* the largest input? –  Apr 30 '18 at 06:47
  • It basically just prints the largest element, instead of the printing the pointer to which it should be assigned. – Tumul Kumar Apr 30 '18 at 06:55

2 Answers2

3

In this line, you write to the place the uninitialised ponter is pointing to.

*max = a[0];

This causes undefined behaviour (or "UB", reading up on it is worth the time) and to be strictly avoided; among other reasons because it is a very likely reason for segfaults.

What you probably want to do is to write the address of the first element into the pointer.

max = &a[0];

Later you write the place the pointer is pointing to, updating it to the max value you have found.

*max = a[i];

Guessing from the rest of your code, you probably want to just keep the address of the max element, so that you can return its address as it is in the input array, without changing the values in the input array (which your currently do, and it seems unlikely that you intend to...).

max = &a[i];

Referring to your comment (that the value is returned, not the pointer):
For returning a pointer (not a value), make sure that you

return max; // the pointer, not the value it is pointing to

Which is what you actually do in the currently shown code version (possibly before an edit...).
Do not return *max; that would return the value.

If by "return" you mean "print", then you need to change the

printf("largest element: %d", *p);

Use p instead of *p and change the format specifier accordingly.
You probably want "largest element at address: %p". (Compare http://en.cppreference.com/w/c/io/fprintf )

printf("largest element at address: %p", p);
Yunnosch
  • 26,130
  • 9
  • 42
  • 54
  • 1
    well, yes I want to keep the address of the max element and return that instead of the actual "value" of the largest element. Right now, the code returns the largest input instead of the pointer to which it's assigned. – Tumul Kumar Apr 30 '18 at 06:34
  • `printf(largest element: %p", p);` does compile and run without a problem, but the output is now neither a number or the pointer, but rather a hexadecimal output `largest element: 0x7ffeeb764af4` – Tumul Kumar Apr 30 '18 at 07:06
  • That is on your environment the representation of a pointer and the way it is supposed to be done. What format of output do you expect? – Yunnosch Apr 30 '18 at 07:09
  • 1
    output should in the form of `a[i]`, as that's how I defined it initially for the element `max` – Tumul Kumar Apr 30 '18 at 07:11
  • Please elaborate that, it is unclear to me. What do you mean by "form of `a[i]`"? And what do you mean by "how I defined for the element `max`"? You defined `max` as a pointer to int. That does not imply a specific form (apart from the standard, implementation specific way as implied by "%p"). `a[i]` in itself does not imply any format either. – Yunnosch Apr 30 '18 at 07:19
  • https://stackoverflow.com/questions/48309094/how-to-print-pointer-address-in-a-c-program – Yunnosch Apr 30 '18 at 07:30
  • By now, this has left the scope of the initial question (on segfault). If your program does not yet work as desired, the problem should be the topic of a separate question. In case I understood the remaining problem correctly, the link above would probably be what your new question would be conisdered a duplicate of. Otherwise elaborate, with sample input, desired output.and what does not satisfy you. You can link to this question to give more background. – Yunnosch Apr 30 '18 at 07:35
  • I consider the question as stated (in the tile) answered. Even the other answer can make the point of having answered the question as represented by the title. Please consider making a new one on the new aspect of what you want to change in your program. – Yunnosch Apr 30 '18 at 07:37
2
 int *max;
 *max = a[0];

This is UB (undefined behavior) since max is not pointing to valid memory and you try to dereference it.

max = &a[0];

Moreover your logic to find the max is wrong. Why do you reset it every time to 0th element. It should be something like.

for(i = 1; i < n; i++)
{
  if(a[i] > *max)
    max = &a[i];
}
melpomene
  • 84,125
  • 8
  • 85
  • 148
Gaurav Sehgal
  • 7,422
  • 2
  • 18
  • 34
  • I did change my code the way you asked me to, but now instead of returning the pointer with the largest element, it's returning the largest element itself. Does this have to do with changing `max=&a[o]`? – Tumul Kumar Apr 30 '18 at 06:28