Thread: .c file and .h file

  1. #1
    Registered User
    Join Date
    Feb 2022
    Location
    Canada, PEI
    Posts
    64

    .c file and .h file

    I create(nothing serious here) a .c file and a .h file and I want to know if I set them up correctly. I want to expose the struct and its elements(struct slice) and the function createSlice. I want everything else to be not be available.

    slice.h
    Code:
    #include <stdlib.h>
    #ifndef SLICE_HH
    #define SLICE_HH
    
    struct slice
    {
        size_t pos;
        size_t length;
        void (*free_slice)(const struct slice *);
        void(*append)(struct slice *, unsigned int);
        unsigned int (*get)(const struct slice *, size_t);
        void (*display)(const struct slice*);
        unsigned int *arr;
    };
    
    struct slice *createSlice(const size_t length);
    
    #endif
    slice.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    struct slice
    {
        size_t pos;
        size_t length;
        void (*free_slice)(const struct slice *);
        void(*append)(struct slice *, unsigned int);
        unsigned int (*get)(const struct slice *, size_t);
        void (*display)(const struct slice*);
        unsigned int *arr;
    };
    
    static void check_allocation(const void *ptr)
    {
        if (!ptr)
        {
            fputs("Allocation failed!", stderr);
            exit(1);
        }
    }
    
    static void display(const struct slice * s) {
        size_t i = 0;
        fprintf(stdout, "Pos: %ld, Length: %ld\n", s->pos, s->length);
        fputs("[ ", stdout);
        for (; i < s->length; i++) {
            fprintf(stdout, "%d ", s->arr[i]);
        }
        fputs("]\n", stdout);
    }
    
    static unsigned int get(const struct slice * s, size_t pos) {
        if (pos <= s->pos) {
            return s->arr[pos];
        }else {
            exit(1);
        }
    }
    
    static void append(struct slice *s, unsigned int value)
    {
        if (s->pos < s->length)
        {
            s->arr[s->pos++] = value;
            return;
        }
        s->arr = realloc(s->arr, (s->length * 2) * sizeof(unsigned int));
        check_allocation(s->arr);
        s->length = s->length * 2;
        s->arr[s->pos++] = value;
    }
    
    static void free_slice(const struct slice *s)
    {
        free((void *)s->arr);
        free((void *)s);
    }
    
    struct slice *createSlice(const size_t length)
    {
        struct slice *s = malloc(sizeof(*s));
        check_allocation(s);
        s->arr = calloc(sizeof(unsigned int), length);
        check_allocation(s->arr);
        s->pos = 0;
        s->length = length;
        s->free_slice = free_slice;
        s->append = append;
        s->get = get;
        s->display = display;
        return s;
    }
    Am I using the static qualifier correctly here?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,126
    slice.h can be this if you want an opaque type.
    Code:
    struct slice;
    struct slice *createSlice(const size_t length);
    And you keep the actual struct definition in slice.c.

    slice.c should include slice.h

    You don't need the casts when calling free.

    Be consistent in your sizeof expressions for your allocator calls.

    Your get() should print a diagnostic before exiting.

    > Am I using the static qualifier correctly here?
    Looks good.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Feb 2022
    Location
    Canada, PEI
    Posts
    64
    @Salem.. Thanks for the additional comments/corrections.

  4. #4
    Registered User
    Join Date
    Apr 2021
    Posts
    92
    In your header file you #include <stdlib.h> outside the include-guard logic.

    This means that your header file always includes another header file, even if it gets included twice.

    In turn, this means that the compiler cannot "optimize away" your header file, since it always takes some action when it gets included.

    Which means that repeatedly including your header file will always force the compiler to open a file, parse the contents, close the file, etc.

    Better you should put the #include inside the guard logic. That will speed up compilation, as well as enabling the "skip-entire-file" logic built in to most compilers.

    And you might want to consider changing to stddef.h instead of stdlib.h, since all you appear to use in the header file is size_t.


Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 11-21-2017, 10:48 AM
  2. Replies: 6
    Last Post: 12-28-2015, 03:36 AM
  3. Replies: 3
    Last Post: 11-28-2012, 09:16 AM
  4. Replies: 11
    Last Post: 09-25-2011, 12:22 AM
  5. Replies: 4
    Last Post: 07-06-2006, 02:53 AM

Tags for this Thread