Skip to content

Instantly share code, notes, and snippets.

@topin89
Last active December 16, 2018 16:14
Show Gist options
  • Save topin89/4cc06ca6037f75f4b3b9b85a0b5e1491 to your computer and use it in GitHub Desktop.
Save topin89/4cc06ca6037f75f4b3b9b85a0b5e1491 to your computer and use it in GitHub Desktop.
Different way to create and zero-init multidimensional arrays
///bin/true;COMPILER_OPTIONS="-std=c99 -g -Wall -Wextra -O0";THIS_FILE="$(cd "$(dirname "$0")"; pwd -P)/$(basename "$0")";OUT_FILE="/tmp/build-cache/$THIS_FILE";mkdir -p "$(dirname "$OUT_FILE")";test "$THIS_FILE" -ot "$OUT_FILE" || $(which clang || which gcc) $COMPILER_OPTIONS -xc "$THIS_FILE" -o "$OUT_FILE" || exit;exec "$OUT_FILE" "$@"
///bin/true;COMPILER_OPTIONS="-g -Wall -Wextra --std=c11 -O3 -fsanitize=address,undefined";THIS_FILE="$(cd "$(dirname "$0")"; pwd -P)/$(basename "$0")";OUT_FILE="/tmp/build-cache/$THIS_FILE";mkdir -p "$(dirname "$OUT_FILE")";test "$THIS_FILE" -ot "$OUT_FILE" || $(which clang || which gcc) $COMPILER_OPTIONS -xc "$THIS_FILE" -o "$OUT_FILE" || exit;exec "$OUT_FILE" "$@"
// For windows dwellers like me, this will totally work in MSYS2, and most likely in Cygwin and MSYS.
// MSYS2 is better, though.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define xstr(a) str(a)
#define str(a) #a
void *(*volatile forced_memset)(void *, int, size_t) = memset;
typedef struct{
int d[10][20][30];
} mdarray;
typedef int nested[20][30];
typedef int fullmda[10][20][30];
//BTW, this is valid
int a;
int a;
int a;
int a;
//And this
int b=10;
int b;
//But not this
//int c=10;
//int c=20;
//global variables (static or not) are zero-initialized
mdarray zeromda;
nested nestedmda[10];
//Valid. This is really the same in the eye of compiler
fullmda plainzeromda;
nested plainzeromda[10];
int plainzeromda[10][20][30];
//int plainzeromda[10][20][31]; // this will produce compilation error
//Dinamic by default is impossible in C
//int * globaldynmda=malloc(sizeof(int)*10*20*30);
//int * globaldynmdazero=calloc(1,sizeof(int)*10*20*30);
void clear(mdarray *mda){
/*for(int i = 0; i<10; ++i)
for(int j = 0; j<20; ++j)
for(int k = 0; k<30; ++k)
mda->d[i][j][k] = 0;*/
*mda = zeromda;
}
//Just to be clear, memset is highly optimized and should
//be used by default. This is for example only.
//All declarations below are the same for a compiler
void clear_plain(fullmda *pmda);
void clear_plain(int (*pmda)[10][20][30]);
void clear_plain(int pmda[][10][20][30]){
for(int i = 0; i<10; ++i)
for(int j = 0; j<20; ++j)
for(int k = 0; k<30; ++k)
(*pmda)[i][j][k] = 0;
};
void clear_nested(int nmda[][20][30], int left_size);
void clear_nested(int nmda[10][20][30], int left_size);
void clear_nested(nested *nmda, int left_size){
for(int i = 0; i<left_size; ++i)
for(int j = 0; j<20; ++j)
for(int k = 0; k<30; ++k)
nmda[i][j][k] = 0;
}
void clear_full_dmda(int *fdmda, int left_size, int middle_size, int right_size){
for(int i = 0; i<left_size; ++i)
for(int j = 0; j<middle_size; ++j)
for(int k = 0; k<right_size; ++k)
fdmda[i*right_size*middle_size + j*right_size+k] = 0;
}
void clear_full_dmda_union(int *fdmda, int left_size, int middle_size, int right_size){
union {
int *sda;
int (*mda)[middle_size][right_size];
} mdau;
mdau.sda=fdmda;
for(int i = 0; i<left_size; ++i)
for(int j = 0; j<middle_size; ++j)
for(int k = 0; k<right_size; ++k)
mdau.mda[i][j][k] = 0;
}
#define clear_full_dmda_macro(mda, left_size, middle_size, right_size) for(int i = 0; i<(left_size); ++i)\
for(int j = 0; j<(middle_size); ++j)\
for(int k = 0; k<(right_size); ++k)\
(mda)[i][j][k] = 0
int isempty(mdarray *mda){
for(int i = 0; i<10; ++i)
for(int j = 0; j<20; ++j)
for(int k = 0; k<30; ++k)
if(mda->d[i][j][k] != 0){
return 0;
}
return 1;
}
int isempty_plain(int (*pmda)[10][20][30]);
int isempty_plain(int pmda[][10][20][30]);
int isempty_plain(fullmda *pmda){
for(int i = 0; i<10; ++i)
for(int j = 0; j<20; ++j)
for(int k = 0; k<30; ++k)
//*pmda[i][j][k] == pmda[i][j][k][0]
//if(pmda[0][i][j][k] != 0){ // same as below
if((*pmda)[i][j][k] != 0){
return 0;
}
return 1;
}
//All declarations below are the same for a compiler
int isempty_nested(int (*nmda)[20][30], int left_size);
int isempty_nested(int nmda[][20][30], int left_size);
int isempty_nested(int nmda[10][20][30], int left_size);
int isempty_nested(nested *nmda, int left_size){
for(int i = 0; i<left_size; ++i)
for(int j = 0; j<20; ++j)
for(int k = 0; k<30; ++k)
if(nmda[i][j][k] != 0){
return 0;
}
return 1;
}
//All declarations below are the same for a compiler
int isempty_full_dmda(int *fdmda, int left_size, int middle_size, int right_size);
int isempty_full_dmda(int fdmda[], int left_size, int middle_size, int right_size);
int isempty_full_dmda(int fdmda[0xDEADBEEF], int left_size, int middle_size, int right_size){
for(int i = 0; i<left_size; ++i)
for(int j = 0; j<middle_size; ++j)
for(int k = 0; k<right_size; ++k)
if(fdmda[i*right_size*middle_size + j*right_size+k] != 0){
return 0;
}
return 1;
}
int isempty_full_dmda_union(int fdmda[0xDEADBEEF], int left_size, int middle_size, int right_size){
union {
int *sda;
int (*mda)[middle_size][right_size];
} mdau;
mdau.sda=fdmda;
for(int i = 0; i<left_size; ++i)
for(int j = 0; j<middle_size; ++j)
for(int k = 0; k<right_size; ++k)
if(mdau.mda[i][j][k] != 0){
return 0;
}
return 1;
}
#define print_empty(mda) printf(xstr(mda)": %s\n", isempty(&(mda))? "EMPTY" : "NON EMPTY")
#define print_empty_nested_typedef(mda) printf(xstr(mda)": %s\n", isempty_nested(mda, 10)? "EMPTY" : "NON EMPTY")
#define print_empty_plain_typedef(mda) printf(xstr(mda)": %s\n", isempty_plain(&(mda))? "EMPTY" : "NON EMPTY")
#define print_empty_partial_dynamic(mda, left_size) printf(xstr(mda)": %s\n", isempty_nested(mda, left_size)? "EMPTY" : "NON EMPTY")
#define print_empty_full_dynamic(mda, left_size, middle_size, right_size) printf(xstr(mda)": %s\n", isempty_full_dmda_union((int *)(mda), left_size, middle_size, right_size)? "EMPTY" : "NON EMPTY")
//#define print_empty_full_dynamic(mda, left_size) printf(xstr(mda)": %s\n", isempty_full_dmda(mda, left_size)? "EMPTY" : "NON EMPTY")
void nested_typedef_mda(){
print_empty_nested_typedef(nestedmda);
printf("\n");
{
nested stackmda[10];
print_empty_nested_typedef(stackmda);
//stackmda=nestedmda; // Sadly, arrays cannot be copy-assigned, even if they are of the same type;
clear_nested(stackmda, 10);
print_empty_nested_typedef(stackmda);
printf("\n");
}
{
nested bracesmda[10] = {0}; //Braces works only in initialization
print_empty_nested_typedef(bracesmda);
printf("\n");
}
//bracesmda={0}; //Error
static nested staticmda[10]; //static variables in functions are also zero-initialized.
print_empty_nested_typedef(staticmda);
staticmda[0][0][0] = 1;
print_empty_nested_typedef(staticmda);
clear_nested(staticmda, 10);
print_empty_nested_typedef(staticmda);
printf("\n");
size_t dynsize = sizeof(nested)*10;
nested *dynmda=(nested *)malloc(dynsize);//By far the best way to get dynamic multidimensional array
if(dynmda){
print_empty_nested_typedef(dynmda);
memset( dynmda, 0, dynsize );//Setting zeroes. This can be optimized away be compiler
print_empty_nested_typedef(dynmda);
free(dynmda);
}
printf("\n");
nested *cryptmda = (nested *)malloc(dynsize);//By far the best way to get dynamic multidimensional array
if(cryptmda){
print_empty_nested_typedef(cryptmda);
forced_memset( cryptmda, 0, dynsize );//Setting zeroes security-friendly way.
print_empty_nested_typedef(cryptmda);
free(cryptmda);
}
printf("\n");
nested *callocmda = (nested *)calloc(1, dynsize);//For your sanity, just make first argument 1 and nothing else
print_empty_nested_typedef(callocmda);
free(callocmda);
}
void plain_typedef_mda(){
print_empty_plain_typedef(plainzeromda);
printf("\n");
{
fullmda stackmda;
print_empty_plain_typedef(stackmda);
//stackmda=plainzeromda; // Sadly, arrays cannot be copy-assigned, even if they are of the same type;
clear_plain(&stackmda);
print_empty_plain_typedef(stackmda);
printf("\n");
}
{
fullmda bracesmda = {0}; //Braces works only in initialization
print_empty_plain_typedef(bracesmda);
printf("\n");
}
//bracesmda={0}; //Error
static fullmda staticmda; //static variables in functions are also zero-initialized.
print_empty_plain_typedef(staticmda);
staticmda[0][0][0] = 1;
print_empty_plain_typedef(staticmda);
clear_plain(&staticmda);
print_empty_plain_typedef(staticmda);
printf("\n");
size_t dynsize = sizeof(fullmda);
fullmda *dynmda=(fullmda *)malloc(dynsize);//By far the best way to get dynamic multidimensional array
if(dynmda){
print_empty_plain_typedef(*dynmda);
memset( dynmda, 0, dynsize );//Setting zeroes. This can be optimized away be compiler
print_empty_plain_typedef(*dynmda);
free(dynmda);
}
printf("\n");
fullmda *cryptmda = (fullmda *)malloc(dynsize);//By far the best way to get dynamic multidimensional array
if(cryptmda){
print_empty_plain_typedef(*cryptmda);
forced_memset( cryptmda, 0, dynsize );//Setting zeroes security-friendly way.
print_empty_plain_typedef(*cryptmda);
free(cryptmda);
}
printf("\n");
fullmda *callocmda = (fullmda *)calloc(1, dynsize);//For your sanity, just make first argument 1 and nothing else
print_empty_plain_typedef(*callocmda);
free(callocmda);
}
void struct_mda(){
print_empty(zeromda);
printf("\n");
mdarray stackmda;
print_empty(stackmda); //Emptiness not guaranteed
stackmda=zeromda; //you can easily assign already zero-initialized array
print_empty(stackmda); //Emptiness not guaranteed
printf("\n");
mdarray bracesmda={0}; //Braces works only in initialization
print_empty(bracesmda);
printf("\n");
//bracesmda={0}; //Error
static mdarray staticmda; //static variables in functions are also zero-initialized.
print_empty(staticmda);
staticmda.d[0][0][0] = 1;
print_empty(staticmda);
clear(&staticmda);
print_empty(staticmda);
printf("\n");
size_t dynsize = sizeof(mdarray);
mdarray *dynmda = (mdarray *)malloc(dynsize);//By far the best way to get dynamic multidimensional array
if(dynmda){
print_empty(*dynmda);
memset( dynmda, 0, dynsize );//Setting zeroes. This can be optimized away be compiler
print_empty(*dynmda);
free(dynmda);
}
printf("\n");
mdarray *cryptmda = (mdarray *)malloc(dynsize);//By far the best way to get dynamic multidimensional array
if(dynmda){
print_empty(*cryptmda);
forced_memset( cryptmda, 0, dynsize );//Setting zeroes security-friendly way.
print_empty(*cryptmda);
free(cryptmda);
}
printf("\n");
mdarray *callocmda = (mdarray *)calloc(1, dynsize);//For your sanity, just make first argument 1 and nothing else
print_empty(*callocmda);
free(callocmda);
}
void partial_dynamic(size_t left_size){
{
//Variable-length array, aka VLA. Part of C99 standart, optional in C11
//Remember, this feature is an abomination in the eyes of Linus
//For it is slow and fragile
//Also, won't work in MSVC
nested stackmda[left_size];
print_empty_partial_dynamic(stackmda, left_size);
//Note that nested is used
clear_nested(stackmda, left_size);
print_empty_partial_dynamic(stackmda, left_size);
printf("\n");
}
size_t dynsize = sizeof(nested)*left_size;
nested *dynmda=(nested *)malloc(dynsize);//By far the best way to get dynamic multidimensional array
if(dynmda){
print_empty_partial_dynamic(dynmda, left_size);
memset( dynmda, 0, dynsize );//Setting zeroes. This can be optimized away be compiler
print_empty_partial_dynamic(dynmda, left_size);
free(dynmda);
}
printf("\n");
nested *cryptmda = (nested *)malloc(dynsize);//By far the best way to get dynamic multidimensional array
if(cryptmda){
print_empty_partial_dynamic(cryptmda, left_size);
forced_memset( cryptmda, 0, dynsize );//Setting zeroes security-friendly way.
print_empty_partial_dynamic(cryptmda, left_size);
free(cryptmda);
}
printf("\n");
nested *callocmda = (nested *)calloc(1, dynsize);//For your sanity, just make first argument 1 and nothing else
print_empty_partial_dynamic(callocmda, left_size);
free(callocmda);
}
void full_dynamic(int left_size, int middle_size, int right_size){
{
//Variable-length array, aka VLA. Part of C99 standart, optional in C11
//Remember, this feature is an abomination in the eyes of Linus
//For it is slow and fragile
//Also, won't work in MSVC
int stackmda[left_size][middle_size][right_size];
print_empty_full_dynamic(stackmda, left_size, middle_size, right_size);
clear_full_dmda_union((int *)stackmda, left_size, middle_size, right_size);
print_empty_full_dynamic(stackmda, left_size, middle_size, right_size);
printf("\n");
}
//Won't work at all for VLA
/*{
nested bracesmda[left_size] = {0}; //Braces works only in initialization
print_empty_partial_dynamic(stackmda, left_size);
printf("\n");
}*/
size_t dynsize = sizeof(int)*left_size*middle_size*right_size;
int (*dynmda)[middle_size][right_size]=malloc(dynsize);//By far the best way to get dynamic multidimensional array
if(dynmda){
print_empty_full_dynamic(dynmda, left_size, middle_size, right_size);
memset( dynmda, 0, dynsize );//Setting zeroes. This can be optimized away be compiler
print_empty_full_dynamic(dynmda, left_size, middle_size, right_size);
dynmda[1][2][3]=10; //Valid
print_empty_full_dynamic(dynmda, left_size, middle_size, right_size);
clear_full_dmda((int *)dynmda, left_size, middle_size, right_size);
print_empty_full_dynamic(dynmda, left_size, middle_size, right_size);
free(dynmda);
}
printf("\n");
int (*cryptmda)[middle_size][right_size] = malloc(dynsize);//By far the best way to get dynamic multidimensional array
if(cryptmda){
print_empty_full_dynamic(cryptmda, left_size, middle_size, right_size);
forced_memset( cryptmda, 0, dynsize );//Setting zeroes security-friendly way.
print_empty_full_dynamic(cryptmda, left_size, middle_size, right_size);
free(cryptmda);
}
printf("\n");
int (*callocmda)[middle_size][right_size] = calloc(1, dynsize);//For your sanity, just make first argument 1 and nothing else
print_empty_full_dynamic(callocmda, left_size, middle_size, right_size);
free(callocmda);
}
int main() {
printf("Fixed size multidimensional array\n");
plain_typedef_mda();
printf("\n\n/************************/\n");
printf("Partial typedef multidimensional array\n");
nested_typedef_mda();
printf("\n\n/************************/\n");
printf("Struct mdarray\n");
struct_mda();
printf("\n\n/************************/\n");
printf("Partially dynamic multidimensional array\n");
partial_dynamic(10);
printf("\n\n/************************/\n");
printf("Fully dynamic multidimensional array\n");
full_dynamic(10,20,30);
/* non_structured */
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment