Skip to content

Instantly share code, notes, and snippets.

@mesbahamin
Created November 20, 2016 01:32
Show Gist options
  • Select an option

  • Save mesbahamin/751bafa81b03bae9a6a4d883d27564ee to your computer and use it in GitHub Desktop.

Select an option

Save mesbahamin/751bafa81b03bae9a6a4d883d27564ee to your computer and use it in GitHub Desktop.
Some examples of functions handling multi-dimensional arrays and pointers.
/* 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