0

I'm relatively new to C. In my program, I have an array of struct, which get appended regularly.

I would like to write a function, which allows me to return the struct from an index to another in this array:

struct Log{
    int sensorState;
    int speed;
};

struct Log myEvent[10000];

Here is what I've done, but it is not working (SIGSEV is thrown):

struct Log *getEvents(int from, int to){
    struct Log *events[to-from+1];

    for(int i=0; i<=to-from;i++){
        events[i]->speed = myEvent[i].speed;
        events[i]->sensorState = myEvent[i].sensorState;
    }
    return events 
} 

Feels like it would be so easy in Java or Python.. but I'm not able to do it in C, I tried so much things, and here I am.

Paazik
  • 3
  • 2
  • 1
    First of all the function doesn't return anything. Secondly, the variable `events` is a *local* variable whose life-time ends when the function return. Any pointer to that array will become invalid immediately as you return from the function. – Some programmer dude May 24 '20 at 12:32
  • I also suggest you do some [rubber duck debugging](https://en.wikipedia.org/wiki/Rubber_duck_debugging) of that copying loop. What are you really copying? – Some programmer dude May 24 '20 at 12:33
  • 1
    You are also missing a semicolon in `struct Log myEvent[10000]` – Ardent Coder May 24 '20 at 12:34
  • 2
    Oh and you dereference the ***uninitialized*** pointers inside the loop. You never make the pointers of the `events` array actually point somewhere. So thats up to three cases of [*undefined behavior*](https://en.wikipedia.org/wiki/Undefined_behavior). – Some programmer dude May 24 '20 at 12:34
  • Does this answer your question? [Getting a sub-array from an existing array](https://stackoverflow.com/questions/943635/getting-a-sub-array-from-an-existing-array) –  May 24 '20 at 12:55

2 Answers2

2

There are several problems with the code presented, among them:

  • Your function declares that it returns a struct Log *, but it does not actually return anything.
  • I suppose that the idea is that the function would return events, but that decays to a struct Log **, whereas you need a struct Log *.
  • Moreover, it would not be useful to return events because that array has automatic storage duration. That is, its lifetime ends when the block execution in which it was created ends. The pointer received from the function in that case would be invalid.
  • You are dereferencing the (pointer) elements of events without having set them to point to anything.

There are two main things you could do:

  1. Return a pointer to the appropriate element of the file-scope myEvent array. This would avoid any need for allocating or copying anything, but that's a double-edged sword. You would then access the same struct Log objects via different indexes on myEvent and on the returned pointer, which might or might not be what you want to achieve. In that case, though, a function is overkill, as all you need is

    struct Log *someEvents = myEvent + from;
    
  2. Alternatively, have your function allocate space dynamically for the wanted number of copies of your struct Log objects, copy the wanted data from myEvent, and return a pointer to the allocated space. In this case, and for the particular contents of your struct Log structure, it would be clearer and more efficient to use memcpy() to do the copying:

    struct Log *getEvents(int from, int to){
        size_t size = (to - from + 1) * sizeof(struct Log);
        struct Log *events = malloc(size);
    
        if (events) {
            memcpy(events, myEvent + from, size);
        } // else malloc failed and 'events' is null
    
        return events;
    } 
    

The dynamically allocated space lives until you explicitly deallocate it with free(). (Which you must eventually do before losing the pointer to the allocated space, else you have a memory leak.)

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • You are mistaken, @Paazik. The returned pointer points to the *first* item of `to - from + 1` items. You may index into it to (with zero-based indices) to access any of those elements. Equivalently, you may use pointer arithmetic to obtain pointers to the other objects. – John Bollinger May 24 '20 at 14:02
0

Pass to the function the Log *myEvent and Log *events and the indexes.

typedef struct Log{
        int sensorState;
        int speed;
    }Log;


    void getEvents(Log *myEvent,Log *events,int from, int to){

        for(int i=from; i<to-from+1;i++){
            events[i].speed = myEvent[i].speed;
            events[i].sensorState = myEvent[i].sensorState;
        }
    } 
Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39