Last active
December 16, 2018 16:14
-
-
Save topin89/4cc06ca6037f75f4b3b9b85a0b5e1491 to your computer and use it in GitHub Desktop.
Different way to create and zero-init multidimensional arrays
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
///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