1
\$\begingroup\$

Array-List-int.h

#ifndef ARRAY_LIST_INT#define ARRAY_LIST_INT#include <stddef.h>#include <stdbool.h>////////////////////////////////////////////////////////////////////////////////// AL_int x; creates an object handler called 'x' for an array list.// The creation of an object handler for an array list must be followed by// AL_int_create_empty() or AL_int_create_empty_with_initial_capacity() before// the array list can be used.typedef struct{    int* arr;    size_t size;    size_t capacity;}AL_int;////////////////////////////////////////////////////////////////////////////////extern const size_t AL_INT_MAX_CAPACITY;// Allocates memory for the array list (which is handled by the object handler// pointed to by 'ptr'), and sets the size and the capacity of the array list to// 0 and 1, respectively.// May cause the program to terminate due to 'out of memory'.void AL_int_create_empty(AL_int* ptr);// Allocates memory for the array list (which is handled by the object handler// pointed to by 'ptr'), and sets the size and the capacity of the array list to// 0 and 'initial_capacity', respectively.// May cause the program to terminate due to 'out of memory'.// 'initial_capacity' must be less than or equal to AL_INT_MAX_CAPACITY.void AL_int_create_empty_with_initial_capacity(AL_int* ptr,                                               size_t initial_capacity);// Frees the memory taken up by the array list (which is handled by the object// handler pointed to by 'ptr').void AL_int_destroy(const AL_int* ptr);////////////////////////////////////////////////////////////////////////////////// Adds 'n' to the end of the array list (which is handled by the object handler// pointed to by 'ptr').// May cause the program to terminate due to 'capacity overflow' or 'out of// memory'.void AL_int_add(AL_int* ptr, int n);// Adds 'n' at the index 'i' to the array list (which is handled by the object// handler pointed to by 'ptr'), shifting elements as required.// May cause the program to terminate due to 'index out of bounds', 'capacity// overflow' or 'out of memory'.void AL_int_add_at_index(AL_int* ptr, ptrdiff_t i, int n);// Clears the array list (which is handled by the object handler pointed to by// 'ptr'), and sets the size and the capacity of the array list to 0 and 1,// respectively.// May cause the program to terminate due to 'out of memory'.void AL_int_clear(AL_int* ptr);// Returns true if 'n' is present in the array list (which is handled by the// object handler pointed to by 'ptr'), and returns false otherwise.bool AL_int_contains(const AL_int* ptr, int n);// Returns the element at the index 'i' in the array list (which is handled by// the object handler pointed to by 'ptr').// May cause the program to terminate due to 'index out of bounds'.int AL_int_get(const AL_int* ptr, ptrdiff_t i);// Returns the index of the first occurrence of 'n' at the range of indices// ['i', 'j') in the array list (which is handled by the object handler pointed// to by 'ptr'), and returns -1 if 'n' is not present at the range of indices in// the array list.ptrdiff_t AL_int_index_of(const AL_int* ptr, ptrdiff_t i, ptrdiff_t j, int n);// Returns true if the array list (which is handled by the object handler// pointed to by 'ptr') is empty (i.e. if the size of the array list is 0), and// returns false otherwise.bool AL_int_is_empty(const AL_int* ptr);// Returns the index of the last occurrence of 'n' at the range of indices// ['i', 'j') in the array list (which is handled by the object handler pointed// to by 'ptr'), and returns -1 if 'n' is not present at the range of indices in// the array list.ptrdiff_t AL_int_last_index_of(const AL_int* ptr, ptrdiff_t i, ptrdiff_t j,                               int n);// Removes the element at the index 'i' from the array list (which is handled by// the object handler pointed to by 'ptr'), shifting elements as required.// May cause the program to terminate due to 'index out of bounds' or 'out of// memory'.void AL_int_remove(AL_int* ptr, ptrdiff_t i);// Removes the elements at the range of indices ['i', 'j') from the array list// (which is handled by the object handler pointed to by 'ptr'), shifting// elements as required.// May cause the program to terminate due to 'index out of bounds' or 'out of// memory'.void AL_int_remove_range(AL_int* ptr, ptrdiff_t i, ptrdiff_t j);// Assigns 'n' to the element at the index 'i' in the array list (which is// handled by the object handler pointed to by 'ptr').// May cause the program to terminate due to 'index out of bounds'.void AL_int_set(AL_int* ptr, ptrdiff_t i, int n);// Returns the size of the array list (which is handled by the object handler// pointed to by 'ptr').size_t AL_int_size(const AL_int* ptr);// Copies the elements of the array list (which is handled by the object handler// pointed to by 'ptr') to a malloc'ed array, and returns a pointer to its first// element.// May cause the program to terminate due to 'out of memory'.int* AL_int_to_array(const AL_int* ptr);////////////////////////////////////////////////////////////////////////////////#endif

Array-List-int.c

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stddef.h>#include <stdint.h>#include <stdbool.h>#include "Array-List-int.h"////////////////////////////////////////////////////////////////////////////////#define AL_INT_INDEX_OUT_OF_BOUNDS "Array List (int) - Index out of Bounds"#define AL_INT_CAPACITY_OVERFLOW "Array List (int) Capacity Overflow"#define AL_INT_OUT_OF_MEMORY "Array List (int) - Out of Memory"// Terminates the program after sending a diagnostic message to stderr.// 'cause' points to the first character of a null-terminated string describing// the cause of termination.// 'caller' points to the first character of a null-terminated string// representing the name of the calling function.static void AL_int_exit(const char* cause, const char* caller){    fprintf(stderr, "%s\n\tat %s()\n", cause, caller);    fprintf(stderr, "\nExiting due to failure\n");    exit(EXIT_FAILURE);}////////////////////////////////////////////////////////////////////////////////const size_t AL_INT_MAX_CAPACITY = ((unsigned long long) PTRDIFF_MAX <    (unsigned long long) SIZE_MAX / (unsigned long long) sizeof (int)) ?        (size_t) PTRDIFF_MAX : SIZE_MAX / sizeof (int);// Increases the capacity of the array list (which is handled by the object// handler pointed to by 'ptr').// May cause the program to terminate due to 'capacity overflow' or 'out of// memory'.static void AL_int_expand(AL_int* ptr){    if (ptr->capacity > AL_INT_MAX_CAPACITY / (size_t) 2)    {        if (ptr->capacity < AL_INT_MAX_CAPACITY)            ptr->capacity = AL_INT_MAX_CAPACITY;        else            AL_int_exit(AL_INT_CAPACITY_OVERFLOW, __func__);    }    else    {        ptr->capacity = ptr->capacity * (size_t) 2;    }    ptr->arr = (int*) realloc((void*) ptr->arr, ptr->capacity * sizeof (int));    if ((void*) ptr->arr == NULL)        AL_int_exit(AL_INT_OUT_OF_MEMORY, __func__);}// Reduces the capacity of the array list (which is handled by the object// handler pointed to by 'ptr').// May cause the program to terminate due to 'out of memory'.static void AL_int_shrink(AL_int* ptr){    if (ptr->size == (size_t) 0)        ptr->capacity = (size_t) 1;    else        ptr->capacity = ptr->size;    ptr->arr = (int*) realloc((void*) ptr->arr, ptr->capacity * sizeof (int));    if ((void*) ptr->arr == NULL)        AL_int_exit(AL_INT_OUT_OF_MEMORY, __func__);}////////////////////////////////////////////////////////////////////////////////// Shifts (by copying) the elements of the array list (which is handled by the// object handler pointed to by 'ptr') at the range of indices [l, ptr->size)// left by 'offset' positions.// It must be ensured that 'l' and 'offset' are valid.static void AL_int_shift_left(const AL_int* ptr, ptrdiff_t l, ptrdiff_t offset){    // for (ptrdiff_t k = l; k < (ptrdiff_t) ptr->size; ++k)    //     (ptr->arr)[k - offset] = (ptr->arr)[k];    memmove((void*) (ptr->arr + l - offset), (void*) (ptr->arr + l),            (ptr->size - (size_t) l) * sizeof (int));}// Shifts (by copying) the elements of the array list (which is handled by the// object handler pointed to by 'ptr') at the range of indices [l, ptr->size)// right by 'offset' positions.// It must be ensured that 'l' and 'offset' are valid, and that the capacity of// the array list is large enough.static void AL_int_shift_right(const AL_int* ptr, ptrdiff_t l, ptrdiff_t offset){    // for (ptrdiff_t k = (ptrdiff_t) ptr->size - (ptrdiff_t) 1; k >= l; --k)    //     (ptr->arr)[k + offset] = (ptr->arr)[k];    memmove((void*) (ptr->arr + l + offset), (void*) (ptr->arr + l),            (ptr->size - (size_t) l) * sizeof (int));}////////////////////////////////////////////////////////////////////////////////void AL_int_create_empty(AL_int* ptr){    ptr->arr = (int*) malloc(sizeof (int));    if ((void*) ptr->arr == NULL)        AL_int_exit(AL_INT_OUT_OF_MEMORY, __func__);    ptr->size = (size_t) 0;    ptr->capacity = (size_t) 1;}void AL_int_create_empty_with_initial_capacity(AL_int* ptr,                                               size_t initial_capacity){    ptr->arr = (int*) malloc(initial_capacity * sizeof (int));    if ((void*) ptr->arr == NULL)        AL_int_exit(AL_INT_OUT_OF_MEMORY, __func__);    ptr->size = (size_t) 0;    ptr->capacity = initial_capacity;}void AL_int_destroy(const AL_int* ptr){    free((void*) ptr->arr);}////////////////////////////////////////////////////////////////////////////////void AL_int_add(AL_int* ptr, int n){    if (ptr->size == ptr->capacity)        AL_int_expand(ptr);    (ptr->arr)[(ptrdiff_t) ptr->size] = n;    ++(ptr->size);}void AL_int_add_at_index(AL_int* ptr, ptrdiff_t i, int n){    if ((i < (ptrdiff_t) 0) || (i > (ptrdiff_t) ptr->size))        AL_int_exit(AL_INT_INDEX_OUT_OF_BOUNDS, __func__);    if (ptr->size == ptr->capacity)        AL_int_expand(ptr);    AL_int_shift_right(ptr, i, (ptrdiff_t) 1);    (ptr->arr)[i] = n;    ++(ptr->size);}void AL_int_clear(AL_int* ptr){    ptr->size = (size_t) 0;    AL_int_shrink(ptr);}bool AL_int_contains(const AL_int* ptr, int n){    for (ptrdiff_t i = (ptrdiff_t) 0; i < (ptrdiff_t) ptr->size; ++i)        if ((ptr->arr)[i] == n)            return true;    return false;}int AL_int_get(const AL_int* ptr, ptrdiff_t i){    if ((i < (ptrdiff_t) 0) || (i >= (ptrdiff_t) ptr->size))        AL_int_exit(AL_INT_INDEX_OUT_OF_BOUNDS, __func__);    return (ptr->arr)[i];}ptrdiff_t AL_int_index_of(const AL_int* ptr, ptrdiff_t i, ptrdiff_t j, int n){    for (ptrdiff_t k = i; k < j; ++k)        if ((ptr->arr)[k] == n)            return k;    return (ptrdiff_t) -1;}bool AL_int_is_empty(const AL_int* ptr){    return ptr->size == (size_t) 0;}ptrdiff_t AL_int_last_index_of(const AL_int* ptr, ptrdiff_t i, ptrdiff_t j,                               int n){    for (ptrdiff_t k = j - (ptrdiff_t) 1; k >= i; --k)        if ((ptr->arr)[k] == n)            return k;    return (ptrdiff_t) -1;}void AL_int_remove(AL_int* ptr, ptrdiff_t i){    AL_int_remove_range(ptr, i, i + (ptrdiff_t) 1);}void AL_int_remove_range(AL_int* ptr, ptrdiff_t i, ptrdiff_t j){    if ((i >= j) || (i < (ptrdiff_t) 0) || (j > (ptrdiff_t) ptr->size))        AL_int_exit(AL_INT_INDEX_OUT_OF_BOUNDS, __func__);    ptrdiff_t offset = j - i;    AL_int_shift_left(ptr, j, offset);    ptr->size -= (size_t) offset;    if (ptr->size < ptr->capacity / 2)        AL_int_shrink(ptr);}void AL_int_set(AL_int* ptr, ptrdiff_t i, int n){    if ((i < (ptrdiff_t) 0) || (i >= (ptrdiff_t) ptr->size))        AL_int_exit(AL_INT_INDEX_OUT_OF_BOUNDS, __func__);    (ptr->arr)[i] = n;}size_t AL_int_size(const AL_int* ptr){    return ptr->size;}int* AL_int_to_array(const AL_int* ptr){    int* array = (int*) malloc(ptr->size * sizeof (int));    if ((void*) ptr->arr == NULL)        AL_int_exit(AL_INT_OUT_OF_MEMORY, __func__);    for (ptrdiff_t i = (ptrdiff_t) 0; i < (ptrdiff_t) ptr->size; ++i)        array[i] = (ptr->arr)[i];    return array;}

Test.c

#include <stdio.h>#include <stdlib.h>#include <stddef.h>#include "Array-List-int.h"int main(void){    AL_int a1;    AL_int_create_empty(&a1);    printf("---------------------------------------------------------------\n");    printf(AL_int_is_empty(&a1) ? "true\n" : "false\n");    printf("---------------------------------------------------------------\n");    AL_int_add(&a1, 10);    AL_int_add(&a1, 20);    AL_int_add(&a1, 30);    printf("%d\n", AL_int_get(&a1, 1));    printf("---------------------------------------------------------------\n");    printf(AL_int_is_empty(&a1) ? "true\n" : "false\n");    printf("%zu\n", AL_int_size(&a1));    printf("---------------------------------------------------------------\n");    for (size_t i = 0; i < AL_int_size(&a1); ++i)    {        printf("%d ", AL_int_get(&a1, i));    }    printf("\n");    printf("---------------------------------------------------------------\n");    AL_int_set(&a1, (ptrdiff_t) 2, 40);    for (size_t i = 0; i < AL_int_size(&a1); ++i)    {        printf("%d ", AL_int_get(&a1, i));    }    printf("\n");    printf("---------------------------------------------------------------\n");    AL_int_add_at_index(&a1, (ptrdiff_t) 1, 50);    for (size_t i = 0; i < AL_int_size(&a1); ++i)    {        printf("%d ", AL_int_get(&a1, i));    }    printf("\n");    printf("---------------------------------------------------------------\n");    AL_int_clear(&a1);    printf("%zu\n", AL_int_size(&a1));    printf("---------------------------------------------------------------\n");    AL_int_add(&a1, 10);    AL_int_add(&a1, 20);    AL_int_add(&a1, 30);    AL_int_add(&a1, 40);    AL_int_add(&a1, 10);    AL_int_add(&a1, 20);    for (size_t i = 0; i < AL_int_size(&a1); ++i)    {        printf("%d ", AL_int_get(&a1, i));    }    printf("\n");    printf(AL_int_contains(&a1, 30) ? "true\n" : "false\n");    printf(AL_int_contains(&a1, 50) ? "true\n" : "false\n");    printf("---------------------------------------------------------------\n");    for (size_t i = 0; i < AL_int_size(&a1); ++i)    {        printf("%d ", AL_int_get(&a1, i));    }    printf("\n");    printf("%td\n", AL_int_index_of(&a1, (ptrdiff_t) 0,                                    (ptrdiff_t) AL_int_size(&a1), 10));    printf("%td\n", AL_int_index_of(&a1, (ptrdiff_t) 0,                                    (ptrdiff_t) AL_int_size(&a1), 30));    printf("%td\n", AL_int_index_of(&a1, (ptrdiff_t) 0,                                    (ptrdiff_t) AL_int_size(&a1), 50));    printf("---------------------------------------------------------------\n");    for (size_t i = 0; i < AL_int_size(&a1); ++i)    {        printf("%d ", AL_int_get(&a1, i));    }    printf("\n");    printf("%td\n", AL_int_last_index_of(&a1, (ptrdiff_t) 0,                                         (ptrdiff_t) AL_int_size(&a1), 10));    printf("%td\n", AL_int_last_index_of(&a1, (ptrdiff_t) 0,                                         (ptrdiff_t) AL_int_size(&a1), 30));    printf("%td\n", AL_int_last_index_of(&a1, (ptrdiff_t) 0,                                         (ptrdiff_t) AL_int_size(&a1), 50));    printf("---------------------------------------------------------------\n");    AL_int_remove(&a1, (ptrdiff_t) 3);    for (size_t i = 0; i < AL_int_size(&a1); ++i)    {        printf("%d ", AL_int_get(&a1, i));    }    printf("\n");    printf("---------------------------------------------------------------\n");    AL_int_remove_range(&a1, (ptrdiff_t) 1, (ptrdiff_t) 3);    int* array = AL_int_to_array(&a1);    for (size_t i = 0; i < AL_int_size(&a1); ++i)    {        printf("%d ", array[i]);    }    printf("\n");    printf("---------------------------------------------------------------\n");    free((void*) array);    AL_int_destroy(&a1);    return 0;}

  • Later, I will add more functions such asAL_int_sort(),AL_int_index_of_binary_search(), etc.

  • I thought about freeing all allocated memory before exiting inAL_int_exit(), but then I couldn't figure out a way to free the memory pertaining to other array lists, or even other data structures, used within the same program. So, in the end, I decided to simply letexit() handle the freeing up of memory.

  • I made the initial capacity and the capacity after clearing equal to 1 in order to avoid dealing withmalloc(0) andrealloc(foo, 0).

  • I thought about not casting the return values ofmalloc() andrealloc(), but I always use a compiler which is good enough to warn me about a missing#include <stdlib.h>. Also, with explicit casts, my program also works as a C++ program.

  • Instead of making a generic array list, I've made a basic array list of int's, as I'm still learning and will later delve into generic programming in C.

  • I decided to keep the object handlers on the stack (similar to the object handlers ofstd::vector's from C++). So, I was forced to defineAL_int in the header file, instead of only declaring it.


Finally, I want to ask a question.

If we have a pointer to const struct, then we cannot modify the members of the struct using that pointer. But, if a member happens to be a pointer, then we can modify the pointed-to item.

For eg.,AL_int_set() will work even ifptr is declared to be apointer-to-const.

How are such situations dealt with?

askedOct 30, 2023 at 19:56
Kushagr Jaiswal's user avatar
\$\endgroup\$
3
  • \$\begingroup\$"How are such situations dealt with?" --> Yes, even withvoid AL_int_set(const AL_int* ptr, ptrdiff_t i, int n) { ... (ptr->arr)[i] = n; },(ptr->arr)[i] = n; is allowed. Please explain why that is a situation to deal with? Do you want memberint* arr; to somehow becomeconst int* arr; becauseptr is nowconst AL_int* ptr?\$\endgroup\$CommentedOct 31, 2023 at 10:20
  • \$\begingroup\$@chux-ReinstateMonica, It does sound weird when you put it that way. Well, I just wanted to have some technique to allow a function to ONLY read from an array list, without having ANY write access to it whatsoever.\$\endgroup\$CommentedOct 31, 2023 at 10:52
  • 2
    \$\begingroup\$WithAL_int_get(), you already have "function to ONLY read from an array list, without having ANY write access to it" by not writing to(ptr->arr)[i]. If you want the compiler to fail-to-compile on code like(ptr->arr)[i] = n;, then member.array needs to beconst int *, which of course messes up functions that you do want to(ptr->arr)[i] = n;. As you have noticed, theconst inconst AL_int* ptr protects the members ofAL_int, but not their "children". To get deep insight, search Stackoverflow for such a question.\$\endgroup\$CommentedOct 31, 2023 at 11:07

2 Answers2

4
\$\begingroup\$

A small review:

Only for the pedantic:PTRDIFF_MAX

OP's assignment ofAL_INT_MAX_CAPACITY is interesting in a subtle way.

const size_t AL_INT_MAX_CAPACITY = ((unsigned long long) PTRDIFF_MAX <    (unsigned long long) SIZE_MAX / (unsigned long long) sizeof (int)) ?        (size_t) PTRDIFF_MAX : SIZE_MAX / sizeof (int);

Apparently OP wants to avoidsigned integer overflow of code that stems from usingptrdiff_t. Whereas, inextreme cases, the size of an allocation can exceedPTRDIFF_MAX, asPTRDIFF_MAX may be less thanSIZE_MAX. This is admirable, if pedantic.

Yet the right-hand side can be simplified.

  • Unnecessary cast:
const size_t AL_INT_MAX_CAPACITY = (/* (unsigned long long) */ PTRDIFF_MAX <    /* (unsigned long long) */ SIZE_MAX / /* (unsigned long long) */ sizeof (int)) ?        (size_t) PTRDIFF_MAX : SIZE_MAX / sizeof (int);
  • The first cast is not needed whensizeof(prtdiff_t) == sizeof(size_t) as in that case, asPTRDIFF_MAX is converted tosize_t and then compared.

  • The first cast is not needed whensizeof(prtdiff_t) > sizeof(size_t) as in that case, asSIZE_MAX is converted toptrdiff_t and then compared. In these 2 cases, the result is as desired without the cast.

  • Yet a castis useful to quiet compiler warnings about comparing types of mixed, sign-ness, so OK, let us leave it in.

  • Leaving in the first cast, then there is no need for the 2nd cast, asSIZE_MAX is expected to have anunsigned type and comparing 2 types of the same sign-ness (after the usual promotions), yet different size is not an issue.

  • Like-wise for the 3rd cast. There is no need to cast as the quotient does not need to be typeunsigned long long,size_t is sufficient.

Now we have:

const size_t AL_INT_MAX_CAPACITY = ((unsigned long long) PTRDIFF_MAX <    SIZE_MAX / sizeof (int)) ?        (size_t) PTRDIFF_MAX : SIZE_MAX / sizeof (int);

And perhaps even consider:

const size_t AL_INT_MAX_CAPACITY = ((uintmax_t) PTRDIFF_MAX <    SIZE_MAX / sizeof (int)) ?        (size_t) PTRDIFF_MAX : SIZE_MAX / sizeof (int);

FWIW, For((unsigned long long) PTRDIFF_MAX < (unsigned long long) SIZE_MAX / (unsigned long long) sizeof (int)) to be true, would be a most unusual machine. As I see it,sizeof (int) would have to be 1. Possible, yet perhaps aunicorn?

So we could use:

const size_t AL_INT_MAX_CAPACITY = SIZE_MAX / sizeof (int);
answeredOct 31, 2023 at 5:54
chux's user avatar
\$\endgroup\$
4
\$\begingroup\$

Typically, library functions should not initiate program termination upon failure. None of your functions should be callingexit() (exit() never fails and never returns to its caller). Instead, consider modifying the library's design to return error codes when failures occur, allowing the caller to decide whether to exit or handle errors gracefully. This way you won't have to worry about freeing all allocated memory before exiting inAL_int_exit().

The documentation should include that the caller is responsible for ensuring that a valid pointer is passed in, and that failure to comply would likely result in undefined behavior (unexpected program termination and potential loss of data).


#define AL_INT_INDEX_OUT_OF_BOUNDS "Array List (int) - Index out of Bounds"#define AL_INT_CAPACITY_OVERFLOW "Array List (int) Capacity Overflow"#define AL_INT_OUT_OF_MEMORY "Array List (int) - Out of Memory"

These macros are better defined as:

static const char *const errors[] = {    "Array List (int) - Index out of Bounds",#define AL_INT_INDEX_OUT_OF_BOUNDS 0    "Array List (int) Capacity Overflow",#define AL_INT_CAPACITY_OVERFLOW   1    "Array List (int) - Out of Memory"#define AL_INT_OUT_OF_MEMORY       2};

Now access them using:

errors[AL_INT_INDEX_OUT_OF_BOUNDS];...

Or you could use anenum for the error codes.


There are a myriad of redundant casts in your code, which not only hamper readability but also add unnecessary complexity to the code. For instance, here:

if (ptr->size == (size_t) 0)        ptr->capacity = (size_t) 1;    else        ptr->capacity = ptr->size;

there is no need to cast the values tosize_t. Consider:

ptr->capacity = !ptr->size ? 1u : ptr->size;// Or, a more straightforward version:ptr->capacity = ptr->size ? ptr->size : 1u;

In the calls tomemmove() andrealloc(), the casts tovoid * are not needed, as there is an implicit conversion to and from avoid * in C. Casting the return ofmalloc() and family is redundant too. In C++, you'd use something like astatic_cast. Why, you won't even userealloc() in C++. C and C++ are different; don't mix them, and don't mix them up. Don't use a C++ compiler to compile C code. This is neither good C code, nor good C++ code.

Why are we castingptr->sizetoptrdiff_t everywhere in the codebase? If you want aptrdiff_t, change the type ofptr->size fromsize_t toptrdiff_t.


Code snippets likeprintf(AL_int_is_empty(&a1) ? "true\n" : "false\n") are used for informational purposes and do not actively verify correctness. Consider using assertions.


Simplify:

#if 0     fprintf(stderr, "%s\n\tat %s()\n", cause, caller);     fprintf(stderr, "\nExiting due to failure\n");#else      fprintf(stderr, "%s\n\tat %s()\n"                     "\nExiting due to failure\n",                     cause, caller);#endif

We don't requireAL_int_create_empty() whenAL_int_create_empty_with_capacity() provides the same functionality. Consider:

void AL_int_create_empty_with_capacity(AL_int* ptr, size_t initial_capacity){    if (initial_capacity < 1) {        initial_capacity = 1;  // Ensure a minimum capacity of 1.    }        ...

Also consider naming it to something better.

answeredOct 30, 2023 at 21:34
Madagascar's user avatar
\$\endgroup\$
0

You mustlog in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.