-
-
Save tlkahn/f546ab40836106a23f5787b9b75ef44e to your computer and use it in GitHub Desktop.
Abstract Data Type using opaque pointers in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include "array_api.h" | |
// abstract array data type types | |
// opaque pointer: | |
// an ADT implementation hidden behind the interface that is abstract to | |
// the client, making it easier to maintain, apply changes and improve | |
// in this example the array_t data type provides a bunch of functins | |
// for manipulating the array, these are accessed through the array.h | |
// interface but the implementation stays hidded in array.c | |
int main(int argc, char const *argv[]) | |
{ | |
// a solid structure can not be difined because the compiler doesn't know | |
// how big the data type is since we didn't add any elements to it | |
// array_t new_array; | |
// 12:11: error: storage size of ‘new_array’ isn’t known | |
// we can however define a pointer to such structure because a pointer is | |
// always of a known size | |
array_t *arr; | |
// create a new abstract array with size 3 | |
arr = array_alloc(3); | |
// set some values | |
array_set(arr, 0, 1); | |
array_set(arr, 1, 2); | |
array_set(arr, 2, 4); | |
// display the array | |
array_print(array_begin(arr), array_end(arr)); | |
// cause the array to grow by setting new indecies | |
array_set(arr, 3, 8); | |
array_set(arr, 6, 64); | |
// display the array, note the empty indecies at 4 and 5 | |
array_print(array_begin(arr), array_end(arr)); | |
// free up the array | |
array_free(arr); | |
return EXIT_SUCCESS; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
// note the absence of array_api.h header | |
// the array.h is used only in adt.c which needs to know of the interface for | |
// the ADT this whole file can be a standalone implementation of the data type | |
// this file can, of course, have it's own header file with function protos | |
// and other junk, but the array_api.h can stays separate | |
// abstract data type implementation // | |
typedef struct array_s | |
{ | |
int m_size; | |
int m_capacity; | |
int * m_data; // actual array data | |
} array_t; | |
// memory management | |
array_t *array_alloc(int size) | |
{ | |
// memory for the return structure | |
array_t* ret = malloc(sizeof(array_t)); | |
// size and capacity | |
ret->m_size = ret->m_capacity = size; | |
// array data allocation | |
ret->m_data = malloc(ret->m_capacity * sizeof(int)); | |
return ret; | |
} | |
void array_free(array_t *arr) | |
{ | |
// free array data and struct itself | |
free(arr->m_data); | |
free(arr); | |
} | |
// manipulations | |
void array_set(array_t *arr, int index, int value) | |
{ | |
// set the size if requested index is bigger than we have | |
if (index >= arr->m_size) | |
{ | |
arr->m_size = index + 1; | |
} | |
// check the capacity | |
if (arr->m_size >= arr->m_capacity) | |
{ | |
int new_capacity = arr->m_capacity * 1.5; // why 1.5? | |
if (new_capacity <= arr->m_size) | |
{ | |
new_capacity = arr->m_size + 1; | |
} | |
// realloc more memory | |
arr->m_data = realloc(arr->m_data, new_capacity * sizeof(int)); | |
arr->m_capacity = new_capacity; | |
} | |
// set the value | |
arr->m_data[index] = value; | |
} | |
void array_print(int *begin, int *end) | |
{ | |
while (begin != end) | |
{ | |
printf("%d ", *begin); | |
begin++; | |
} | |
} | |
// array status info | |
int *array_begin(const array_t *arr) | |
{ | |
return arr->m_data; | |
} | |
int *array_end(const array_t *arr) | |
{ | |
return arr->m_data + arr->m_size; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef ARRAY_H | |
#define ARRAY_H | |
// Abstract Data Type | |
// | |
// This demonstrates information hiding (encapsulation) using C | |
// If the declaration of array_t or the internal structure were to change | |
// it would be unnecessary to recompile other modules, unless the API was also | |
// changed | |
// object of an incomplete type, why works with or without *? | |
typedef struct array_s *array_t; | |
// interface for the ADT | |
array_t *array_alloc(int size); | |
void array_free(array_t *arr); | |
void array_set(array_t *arr, int index, int value); | |
int *array_begin(array_t *arr); | |
int *array_end(array_t *arr); | |
void array_print(int *begin, int *end); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment