Created
November 20, 2016 01:32
-
-
Save mesbahamin/751bafa81b03bae9a6a4d883d27564ee to your computer and use it in GitHub Desktop.
Some examples of functions handling multi-dimensional arrays and pointers.
This file contains hidden or 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
| /* Some examples of functions handling arrays and pointers | |
| * Created by Amin Mesbah | |
| * | |
| * This is free and unencumbered software released into the public domain. | |
| * | |
| * Anyone is free to copy, modify, publish, use, compile, sell, or | |
| * distribute this software, either in source code form or as a compiled | |
| * binary, for any purpose, commercial or non-commercial, and by any | |
| * means. | |
| * | |
| * In jurisdictions that recognize copyright laws, the author or authors | |
| * of this software dedicate any and all copyright interest in the | |
| * software to the public domain. We make this dedication for the benefit | |
| * of the public at large and to the detriment of our heirs and | |
| * successors. We intend this dedication to be an overt act of | |
| * relinquishment in perpetuity of all present and future rights to this | |
| * software under copyright law. | |
| * | |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
| * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
| * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
| * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| * OTHER DEALINGS IN THE SOFTWARE. | |
| * | |
| * For more information, please refer to <http://unlicense.org> | |
| */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <time.h> | |
| #define COLUMNS 5 | |
| // TODO: understand this | |
| typedef struct IntArray2d IntArray2d; | |
| struct IntArray2d | |
| { | |
| int rows; | |
| int columns; | |
| int **data; | |
| }; | |
| void show_array(int size, const int array[size]); | |
| void show_2d_array(const int array[][COLUMNS], int rows); | |
| void show_variable_length_2d_array(int rows, int columns, const int array[rows][columns]); | |
| void show_2d_array_pointer(int rows, int columns, int **array); | |
| int* return_array(int size, int initial_value); | |
| IntArray2d return_2d_array_in_struct(int rows, int columns, int initial_value); | |
| void free_2d_array_in_struct(IntArray2d *array_struct); | |
| int main(void) | |
| { | |
| const int ROWS = 3; | |
| int matrix[ROWS][COLUMNS]; | |
| int count = 1; | |
| for (int r = 0; r < ROWS; ++r) | |
| { | |
| for (int c = 0; c < COLUMNS; ++c) | |
| { | |
| matrix[r][c] = count++; | |
| } | |
| } | |
| printf("matrix[2][1] == %d == *(*(matrix + 2) + 1) == %d\n", matrix[2][1], *(*(matrix + 2) + 1)); | |
| printf("\nshow_array(const int array[][COLUMNS], int rows)\n"); | |
| show_2d_array(matrix, ROWS); | |
| printf("\nshow_variable_length_array(int rows, int columns, const int array[rows][columns]\n"); | |
| show_variable_length_2d_array(ROWS, COLUMNS, matrix); | |
| int returned_array_size = 15; | |
| int *returned_array = return_array(returned_array_size, 3); | |
| if (returned_array) | |
| { | |
| printf("\nshow_array(int size, const int array[size])\n"); | |
| show_array(returned_array_size, returned_array); | |
| free(returned_array); | |
| } | |
| IntArray2d returned_2d_array = return_2d_array_in_struct(3, 2, 44); | |
| if (returned_2d_array.data) | |
| { | |
| printf("\nshow_2d_array_pointer(int rows, int columns, int **array)\n"); | |
| show_2d_array_pointer(returned_2d_array.rows, returned_2d_array.columns, returned_2d_array.data); | |
| free_2d_array_in_struct(&returned_2d_array); | |
| } | |
| return(0); | |
| } | |
| /* This function uses a variable length array (VLA). | |
| * VLAs were introduced in C99. 'size' is passed as | |
| * a variable parameter. Note that the order of the | |
| * parameters matters. | |
| */ | |
| void show_array(int size, const int array[size]) | |
| { | |
| for (int i = 0; i < size; ++i) | |
| { | |
| printf("array[%d]: %d\n", i, array[i]); | |
| } | |
| } | |
| /* This function displays the contents of a 2D array. | |
| * The number of rows is a variable parameter, but the | |
| * number of columns must be a constant. This is because | |
| * arrays decay into pointers when passed as function | |
| * parameters, so: | |
| * | |
| * const int array[][5] | |
| * | |
| * becomes: | |
| * | |
| * const int (*array)[5] | |
| * | |
| * 'array' is a pointer to an array of 5 const ints. | |
| * A pointer to an array of a different size is a | |
| * different type of pointer. | |
| */ | |
| void show_2d_array(const int array[][COLUMNS], int rows) | |
| { | |
| for (int r = 0; r < rows; ++r) | |
| { | |
| for (int c = 0; c < COLUMNS; ++c) | |
| { | |
| printf("array[%d][%d]: %d\n", r, c, array[r][c]); | |
| } | |
| } | |
| } | |
| /* This function uses variable length arrays (VLAs), | |
| * which were introduced in C99. Its body is identical | |
| * to 'show_2d_array()', but 'rows' and 'columns' can both | |
| * be variable parameters. Note that the order of the | |
| * parameters matters. | |
| */ | |
| void show_variable_length_2d_array(int rows, int columns, const int array[rows][columns]) | |
| { | |
| for (int r = 0; r < rows; ++r) | |
| { | |
| for (int c = 0; c < columns; ++c) | |
| { | |
| printf("array[%d][%d]: %d\n", r, c, array[r][c]); | |
| } | |
| } | |
| } | |
| /* Note: 'int **array' could be 'int *array[columns]' | |
| */ | |
| void show_2d_array_pointer(int rows, int columns, int **array) | |
| { | |
| for (int r = 0; r < rows; ++r) | |
| { | |
| for (int c = 0; c < columns; ++c) | |
| { | |
| printf("array[%d][%d]: %d\n", r, c, array[r][c]); | |
| } | |
| } | |
| } | |
| /* This function creates an array of a given size, | |
| * initializes all its slots to a given initial_value, | |
| * and returns a pointer to it. | |
| * Note that malloc is used here to dynamically | |
| * allocate the memory for the array. One might | |
| * think we could use variable length arrays here: | |
| * | |
| * int result[size]; | |
| * | |
| * but that would result in a segfault. The memory | |
| * for result would be allocated on the stack. result | |
| * would be a local variable of automatic duration. The | |
| * function would return a pointer to the beginning | |
| * of that memory, and the function would exit, | |
| * deallocating the memory. The pointer will no | |
| * longer point to a valid memory location. Instead | |
| * we use malloc, which allocates the memory on the | |
| * heap, and allows it to remain allocated after the | |
| * function exits. | |
| * | |
| * We could also make result static: | |
| * | |
| * static int result[size]; | |
| * | |
| * The drawback is that the same memory will be used | |
| * every time the function is called, overwriting | |
| * the data stored previously. | |
| * | |
| * Finally, since malloc is used here, it is important | |
| * to remember to free the memory when it is no longer | |
| * needed. | |
| */ | |
| int* return_array(int size, int initial_value) | |
| { | |
| int *result = malloc(sizeof(int) * size); | |
| // Return NULL if malloc fails to allocate memory. | |
| // We could also exit with an error here. | |
| if (result == NULL) | |
| { | |
| return NULL; | |
| } | |
| for (int i = 0; i < size; ++i) | |
| { | |
| result[i] = initial_value; | |
| } | |
| return result; | |
| } | |
| /* This function dynamically allocates a 2d array, | |
| * initializes its values, and returns a pointer | |
| * to it in a struct that also contains the array's | |
| * dimensions. | |
| */ | |
| IntArray2d return_2d_array_in_struct(int rows, int columns, int initial_value) | |
| { | |
| IntArray2d result; | |
| result.rows = rows; | |
| result.columns = columns; | |
| result.data = malloc(rows * sizeof(int *)); | |
| if (result.data == NULL) | |
| { | |
| fprintf(stderr, "Out of memory\n"); | |
| return result; | |
| } | |
| for (int r = 0; r < rows; ++r) | |
| { | |
| result.data[r] = malloc(columns * sizeof(int)); | |
| if (result.data[r] == NULL) | |
| { | |
| fprintf(stderr, "Out of memory\n"); | |
| return result; | |
| } | |
| } | |
| for (int r = 0; r < rows; ++r) | |
| { | |
| for (int c = 0; c < columns; ++c) | |
| { | |
| result.data[r][c] = initial_value; | |
| } | |
| } | |
| return result; | |
| } | |
| /* Deallocate all chunks of memory pointed to | |
| * by the second level pointers, then the first | |
| * level pointer. | |
| */ | |
| void free_2d_array_in_struct(IntArray2d *array_struct) | |
| { | |
| for (int r = 0; r < array_struct->rows; ++r) | |
| { | |
| free(array_struct->data[r]); | |
| } | |
| free(array_struct->data); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment