Skip to main content
added 15 characters in body
Source Link
Davislor
  • 9.1k
  • 19
  • 39

A few points less important than the one Toby Speight made in his excellent answer.

Naming Conventions

You have create_dynamic_array() but freeDynamicArray(). Then, you name functions length() and push(), which are likely to collide with identifiers in the rest of the program if you try to re-use this code.

Since C doesn’t have namespaces, best practice is to pick choose a convention like camelCase or snake_case, then pick a prefix for every public function in the module, for example dyn_arr_ (dyn_arr_c_ for functions that take a const dynamic_array* as the first argument, DYN_ARR_ for macros defined by the package). It is much more reasonable to warn other coders not to use names that start with dyn_arr_ than to break code that uses the identifier length.

Allocation

This library only supports creating dynamic arrays on the heap, so you cannot store them in data structures or create local dynamic arrays.

There is one potential advantage of this: you could in theory declare dynamic_array as an incomplete type in the header, like FILE, which can hide implementation details. That’s not the trade-off I think I would make with a dynamic array in C, but it’s valid. I suggest you mostly want short inline functions.

I recommend you take a leaf out of POSIX’s book and define a macro like

#define DYN_ARR_INITIALIZER ((dynamic_array)\
    {.size = 0U, .capacity = 0U, .data = NULL})

This is similar to PTHREAD_MUTEX_INITIALIZER or PTHREAD_COND_INITIALIZER, and lets you declare

dynamic_array foo = DYN_ARR_INITIALIZER;

You might even consider making the other initialization functions require a valid initialization like this, for example,

dynamic_array foo = DYN_ARR_INITIALIZER;
dynamic_array bar = DYN_ARR_INITIALIZER;
dynamic_array_fill(&foo, &source, 8, sizeof(source));
dyn_array_resize(&foo, 42);
dyn_array_swap(&bar, &foo); // Destination goes first.

This adds a tiny amount of overhead to initialization. In my opinion, it’s worth the cost because it forces any overwrite of a dynamic_array to free the target. If there were a function that directly overwrote an uninitialized dynamic_array, the compiler would also allow it to overwrite an initialized dynamic_array, and leak memory.

All initial allocations would then use realloc(). If the array was previously empty, this passes NULL as the previous address to realloc(), which makes it behave like malloc(), You could then optionally zero out the newly-allocated bytes with memset().

A few points less important than the one Toby Speight made in his excellent answer.

Naming Conventions

You have create_dynamic_array() but freeDynamicArray(). Then, you name functions length() and push(), which are likely to collide with identifiers in the rest of the program if you try to re-use this code.

Since C doesn’t have namespaces, best practice is to pick choose a convention like camelCase or snake_case, then pick a prefix for every public function in the module, for example dyn_arr_ (dyn_arr_c_ for functions that take a const dynamic_array* as the first argument, DYN_ARR_ for macros defined by the package). It is much more reasonable to warn other coders not to use names that start with dyn_arr_ than to break code that uses the identifier length.

Allocation

This library only supports creating dynamic arrays on the heap, so you cannot store them in data structures or create local dynamic arrays.

There is one potential advantage of this: you could in theory declare dynamic_array as an incomplete type in the header, like FILE, which can hide implementation details. That’s not the trade-off I think I would make with a dynamic array in C, but it’s valid. I suggest you mostly want short inline functions.

I recommend you take a leaf out of POSIX’s book and define a macro like

#define DYN_ARR_INITIALIZER ((dynamic_array)\
    {.size = 0U, .capacity = 0U, .data = NULL})

This is similar to PTHREAD_MUTEX_INITIALIZER or PTHREAD_COND_INITIALIZER, and lets you declare

dynamic_array foo = DYN_ARR_INITIALIZER;

You might even consider making the other initialization functions require a valid initialization like this, for example,

dynamic_array foo = DYN_ARR_INITIALIZER;
dynamic_array bar = DYN_ARR_INITIALIZER;
dynamic_array_fill(&foo, &source, 8, sizeof(source));
dyn_array_resize(&foo, 42);
dyn_array_swap(&bar, &foo); // Destination goes first.

This adds a tiny amount of overhead to initialization. In my opinion, it’s worth the cost because it forces any overwrite of a dynamic_array to free the target. If there were a function that directly overwrote an uninitialized dynamic_array, the compiler would also allow it to overwrite an initialized dynamic_array, and leak memory.

All initial allocations would then use realloc(). If the array was previously empty, this passes NULL as the previous address to realloc(), which makes it behave like malloc(), You could then optionally zero out the newly-allocated bytes with memset().

A few points less important than the one Toby Speight made in his excellent answer.

Naming Conventions

You have create_dynamic_array() but freeDynamicArray(). Then, you name functions length() and push(), which are likely to collide with identifiers in the rest of the program if you try to re-use this code.

Since C doesn’t have namespaces, best practice is to pick choose a convention like camelCase or snake_case, then pick a prefix for every public function in the module, for example dyn_arr_ (dyn_arr_c_ for functions that take a const dynamic_array* as the first argument, DYN_ARR_ for macros defined by the package). It is much more reasonable to warn other coders not to use names that start with dyn_arr_ than to break code that uses the identifier length.

Allocation

This library only supports creating dynamic arrays on the heap, so you cannot store them in data structures or create local dynamic arrays.

There is one potential advantage of this: you could in theory declare dynamic_array as an incomplete type in the header, like FILE, which can hide implementation details. That’s not the trade-off I think I would make with a dynamic array in C, but it’s valid. I suggest you mostly want short inline functions.

I recommend you take a leaf out of POSIX’s book and define a macro like

#define DYN_ARR_INITIALIZER ((dynamic_array)\
    {.size = 0U, .capacity = 0U, .data = NULL})

This is similar to PTHREAD_MUTEX_INITIALIZER or PTHREAD_COND_INITIALIZER, and lets you declare

dynamic_array foo = DYN_ARR_INITIALIZER;

You might even consider making the other initialization functions require a valid initialization like this, for example,

dynamic_array foo = DYN_ARR_INITIALIZER;
dynamic_array bar = DYN_ARR_INITIALIZER;
dynamic_array_fill(&foo, &source, 8, sizeof(source));
dyn_array_resize(&foo, 42);
dyn_array_swap(&bar, &foo);

This adds a tiny amount of overhead to initialization. In my opinion, it’s worth the cost because it forces any overwrite of a dynamic_array to free the target. If there were a function that directly overwrote an uninitialized dynamic_array, the compiler would also allow it to overwrite an initialized dynamic_array, and leak memory.

All initial allocations would then use realloc(). If the array was previously empty, this passes NULL as the previous address to realloc(), which makes it behave like malloc(), You could then optionally zero out the newly-allocated bytes with memset().

added 15 characters in body
Source Link
Davislor
  • 9.1k
  • 19
  • 39

A few points less important than the one Toby Speight made in his excellent answer.

Naming Conventions

You have create_dynamic_array() but freeDynamicArray(). Then, you name functions length() and push(), which are likely to collide with identifiers in the rest of the program if you try to re-use this code.

Since C doesn’t have namespaces, best practice is to pick choose a convention like camelCase or snake_case, then pick a prefix for every public function in the module, for example dyn_arr_ (dyn_arr_c_ for functions that take a const dynamic_array* as the first argument, DYN_ARR_ for macros defined by the package). It is much more reasonable to warn other coders not to use names that start with dyn_arr_ than to break code that uses the identifier length.

Allocation

This library only supports creating dynamic arrays on the heap, so you cannot store them in data structures or create local dynamic arrays.

There is one potential advantage of this: you could in theory declare dynamic_array as an incomplete type in the header, like FILE, which can hide implementation details. That’s not the trade-off I think I would make with a dynamic array in C, but it’s valid. I suggest you mostly want short inline functions.

I recommend you take a leaf out of POSIX’s book and define a macro like

#define DYN_ARRAY_INITDYN_ARR_INITIALIZER ((dynamic_array)\
    {.size = 0U, .capacity = 0U, .data = NULL})

whichThis is similar to PTHREAD_MUTEX_INITIALIZER or PTHREAD_COND_INITIALIZER, and lets you declare

dynamic_array foo = DYN_ARRAY_INIT;DYN_ARR_INITIALIZER;

You might even consider making the other initialization functions require a valid initialization like this, for example,

dynamic_array foo = DYN_ARRAY_INIT;DYN_ARR_INITIALIZER;
dynamic_array bar = DYN_ARRAY_INIT;DYN_ARR_INITIALIZER;
dynamic_array_fill(&foo, &source, 8, sizeof(source));
dyn_array_resize(&foo, 42);
dyn_array_swap(&bar, &foo); // Destination goes first.

This adds a tiny amount of overhead to initialization. In my opinion, it’s worth the cost because it forces any overwrite of a dynamic_array to free the target. If there were a function that directly overwrote an uninitialized dynamic_array, the compiler would also allow it to overwrite an initialized dynamic_array, and leak memory.

All initial allocations would then use realloc(). If the array was previously empty, this passes NULL as the previous address to realloc(), which makes it behave like malloc(), You could then optionally zero out the newly-allocated bytes with memset().

A few points less important than the one Toby Speight made in his excellent answer.

Naming Conventions

You have create_dynamic_array() but freeDynamicArray(). Then, you name functions length() and push(), which are likely to collide with identifiers in the rest of the program if you try to re-use this code.

Since C doesn’t have namespaces, best practice is to pick choose a convention like camelCase or snake_case, then pick a prefix for every public function in the module, for example dyn_arr_ (dyn_arr_c_ for functions that take a const dynamic_array* as the first argument, DYN_ARR_ for macros defined by the package). It is much more reasonable to warn other coders not to use names that start with dyn_arr_ than to break code that uses the identifier length.

Allocation

This library only supports creating dynamic arrays on the heap, so you cannot store them in data structures or create local dynamic arrays.

There is one potential advantage of this: you could in theory declare dynamic_array as an incomplete type in the header, like FILE, which can hide implementation details. That’s not the trade-off I think I would make with a dynamic array in C, but it’s valid. I suggest you mostly want short inline functions.

I recommend you take a leaf out of POSIX’s book and define a macro like

#define DYN_ARRAY_INIT ((dynamic_array)\
    {.size = 0U, .capacity = 0U, .data = NULL})

which lets you declare

dynamic_array foo = DYN_ARRAY_INIT;

You might even consider making the other initialization functions require a valid initialization like this, for example,

dynamic_array foo = DYN_ARRAY_INIT;
dynamic_array bar = DYN_ARRAY_INIT;
dynamic_array_fill(&foo, &source, 8, sizeof(source));
dyn_array_resize(&foo, 42);
dyn_array_swap(&bar, &foo); // Destination goes first.

This adds a tiny amount of overhead to initialization. In my opinion, it’s worth the cost because it forces any overwrite of a dynamic_array to free the target. If there were a function that directly overwrote an uninitialized dynamic_array, the compiler would also allow it to overwrite an initialized dynamic_array, and leak memory.

All initial allocations would then use realloc(). If the array was previously empty, this passes NULL as the previous address to realloc(), which makes it behave like malloc(), You could then optionally zero out the newly-allocated bytes with memset().

A few points less important than the one Toby Speight made in his excellent answer.

Naming Conventions

You have create_dynamic_array() but freeDynamicArray(). Then, you name functions length() and push(), which are likely to collide with identifiers in the rest of the program if you try to re-use this code.

Since C doesn’t have namespaces, best practice is to pick choose a convention like camelCase or snake_case, then pick a prefix for every public function in the module, for example dyn_arr_ (dyn_arr_c_ for functions that take a const dynamic_array* as the first argument, DYN_ARR_ for macros defined by the package). It is much more reasonable to warn other coders not to use names that start with dyn_arr_ than to break code that uses the identifier length.

Allocation

This library only supports creating dynamic arrays on the heap, so you cannot store them in data structures or create local dynamic arrays.

There is one potential advantage of this: you could in theory declare dynamic_array as an incomplete type in the header, like FILE, which can hide implementation details. That’s not the trade-off I think I would make with a dynamic array in C, but it’s valid. I suggest you mostly want short inline functions.

I recommend you take a leaf out of POSIX’s book and define a macro like

#define DYN_ARR_INITIALIZER ((dynamic_array)\
    {.size = 0U, .capacity = 0U, .data = NULL})

This is similar to PTHREAD_MUTEX_INITIALIZER or PTHREAD_COND_INITIALIZER, and lets you declare

dynamic_array foo = DYN_ARR_INITIALIZER;

You might even consider making the other initialization functions require a valid initialization like this, for example,

dynamic_array foo = DYN_ARR_INITIALIZER;
dynamic_array bar = DYN_ARR_INITIALIZER;
dynamic_array_fill(&foo, &source, 8, sizeof(source));
dyn_array_resize(&foo, 42);
dyn_array_swap(&bar, &foo); // Destination goes first.

This adds a tiny amount of overhead to initialization. In my opinion, it’s worth the cost because it forces any overwrite of a dynamic_array to free the target. If there were a function that directly overwrote an uninitialized dynamic_array, the compiler would also allow it to overwrite an initialized dynamic_array, and leak memory.

All initial allocations would then use realloc(). If the array was previously empty, this passes NULL as the previous address to realloc(), which makes it behave like malloc(), You could then optionally zero out the newly-allocated bytes with memset().

added 267 characters in body
Source Link
Davislor
  • 9.1k
  • 19
  • 39

A few points less important than the one Toby Speight made in his excellent answer.

Naming Conventions

You have create_dynamic_array() but freeDynamicArray(). Then, you name functions length() and push(), which are likely to collide with identifiers in the rest of the program if you try to re-use this code.

Since C doesn’t have namespaces, best practice is to pick choose a convention like camelCase or snake_case, then pick a prefix for every public function in the module, for example dyn_arr_ (dyn_arr_c_ for functions that take a const dynamic_array* as the first argument, DYN_ARR_ for macros defined by the package). It is much more reasonable to warn other coders not to use names that start with dyn_arr_ than to break code that uses the identifier length.

Allocation

This library only supports creating dynamic arrays on the heap, so you cannot store them in data structures or create local dynamic arrays.

There is one potential advantage of this: you could in theory declare dynamic_array as an incomplete type in the header, like FILE, which can hide implementation details. That’s not the trade-off I think I would make with a dynamic array in C, but it’s valid. I suggest you mostly want short inline functions.

I recommend you take a leaf out of POSIX’s book and define a macro like

#define DYN_ARRAY_INIT ((dynamic_array)\
    {.size = 0U, .capacity = 0U, .data = NULL})

which lets you declare

dynamic_array foo = DYN_ARRAY_INIT;

You might even consider making the other initialization functions require a valid initialization like this, for example,

dynamic_array foo = DYN_ARRAY_INIT;
dynamic_array bar = DYN_ARRAY_INIT;
dynamic_array_fill(&foo, &source, 8, sizeof(source));
dyn_array_resize(&foo, 42);
dyn_array_swap(&bar, &foo); // Destination goes first.

This adds a tiny amount of overhead to initialization. In my opinion, it’s worth the cost because it forces any overwrite of a dynamic_array to free the target. If there were a function that directly overwrote an uninitialized dynamic_array, the compiler would also allow it to overwrite an initialized dynamic_array, and leak memory.

All initial allocations would then use realloc(). If the array was previously empty, this passes NULL as the previous address to realloc(), which makes it behave like malloc(), You could then optionally zero out the newly-allocated bytes with memset().

A few points less important than the one Toby Speight made in his excellent answer.

Naming Conventions

You have create_dynamic_array() but freeDynamicArray(). Then, you name functions length() and push(), which are likely to collide with identifiers in the rest of the program if you try to re-use this code.

Since C doesn’t have namespaces, best practice is to pick choose a convention like camelCase or snake_case, then pick a prefix for every public function in the module, for example dyn_arr_ (dyn_arr_c_ for functions that take a const dynamic_array* as the first argument, DYN_ARR_ for macros defined by the package). It is much more reasonable to warn other coders not to use names that start with dyn_arr_ than to break code that uses the identifier length.

Allocation

This library only supports creating dynamic arrays on the heap, so you cannot store them in data structures or create local dynamic arrays.

There is one potential advantage of this: you could in theory declare dynamic_array as an incomplete type in the header, like FILE, which can hide implementation details. That’s not the trade-off I think I would make with a dynamic array in C, but it’s valid. I suggest you mostly want short inline functions.

I recommend you take a leaf out of POSIX’s book and define a macro like

#define DYN_ARRAY_INIT ((dynamic_array)\
    {.size = 0U, .capacity = 0U, .data = NULL})

which lets you declare

dynamic_array foo = DYN_ARRAY_INIT;

You might even consider making the other initialization functions require a valid initialization like this, for example,

dynamic_array foo = DYN_ARRAY_INIT;
dynamic_array bar = DYN_ARRAY_INIT;
dynamic_array_fill(&foo, &source, 8, sizeof(source));
dyn_array_resize(&foo, 42);
dyn_array_swap(&bar, &foo); // Destination goes first.

This adds a tiny amount of overhead to initialization. In my opinion, it’s worth the cost because it forces any overwrite of a dynamic_array to free the target. If there were a function that directly overwrote an uninitialized dynamic_array, the compiler would also allow it to overwrite an initialized dynamic_array, and leak memory.

A few points less important than the one Toby Speight made in his excellent answer.

Naming Conventions

You have create_dynamic_array() but freeDynamicArray(). Then, you name functions length() and push(), which are likely to collide with identifiers in the rest of the program if you try to re-use this code.

Since C doesn’t have namespaces, best practice is to pick choose a convention like camelCase or snake_case, then pick a prefix for every public function in the module, for example dyn_arr_ (dyn_arr_c_ for functions that take a const dynamic_array* as the first argument, DYN_ARR_ for macros defined by the package). It is much more reasonable to warn other coders not to use names that start with dyn_arr_ than to break code that uses the identifier length.

Allocation

This library only supports creating dynamic arrays on the heap, so you cannot store them in data structures or create local dynamic arrays.

There is one potential advantage of this: you could in theory declare dynamic_array as an incomplete type in the header, like FILE, which can hide implementation details. That’s not the trade-off I think I would make with a dynamic array in C, but it’s valid. I suggest you mostly want short inline functions.

I recommend you take a leaf out of POSIX’s book and define a macro like

#define DYN_ARRAY_INIT ((dynamic_array)\
    {.size = 0U, .capacity = 0U, .data = NULL})

which lets you declare

dynamic_array foo = DYN_ARRAY_INIT;

You might even consider making the other initialization functions require a valid initialization like this, for example,

dynamic_array foo = DYN_ARRAY_INIT;
dynamic_array bar = DYN_ARRAY_INIT;
dynamic_array_fill(&foo, &source, 8, sizeof(source));
dyn_array_resize(&foo, 42);
dyn_array_swap(&bar, &foo); // Destination goes first.

This adds a tiny amount of overhead to initialization. In my opinion, it’s worth the cost because it forces any overwrite of a dynamic_array to free the target. If there were a function that directly overwrote an uninitialized dynamic_array, the compiler would also allow it to overwrite an initialized dynamic_array, and leak memory.

All initial allocations would then use realloc(). If the array was previously empty, this passes NULL as the previous address to realloc(), which makes it behave like malloc(), You could then optionally zero out the newly-allocated bytes with memset().

Source Link
Davislor
  • 9.1k
  • 19
  • 39
Loading