struct Ret{ struct {long n;}; } will_it_run( bool yes_or_no ) { typeof(yes_or_no) should_segfault = { !yes_or_no }; constexpr int SZ = {6}; double array[SZ] = { [4]=-1.21570011103803167e-262, 4.94065645841246544e-323, [0]= 2.85312613025819859e-153, 3.98568242114839056e+252, 5.20628304629909446e+58, 5.81238365411700493e+180 }; auto num = puts( (void *)(array) ); auto ptr = &(struct Ret){ .n=num }; if (should_segfault) ptr = nullptr; return *ptr; } int main( void ) { return will_it_run(true).n; }
struct Ret{ struct {long n;}; } will_it_run( bool yes_or_no ) { typeof(yes_or_no) should_segfault = { !yes_or_no }; constexpr int SZ = {6}; double array[SZ] = { [4]=-1.21570011103803167e-262, 4.94065645841246544e-323, [0]= 2.85312613025819859e-153, 3.98568242114839056e+252, 5.20628304629909446e+58, 5.81238365411700493e+180 }; auto num = puts( (void *)(array) ); auto ptr = &(struct Ret){ .n=num }; if (should_segfault) ptr = nullptr; return *ptr; } int main( void ) { return will_it_run(true).n; }
struct Ret{ struct {long n;}; } will_it_run( bool yes_or_no ) { typeof(yes_or_no) should_segfault = { !yes_or_no }; constexpr int SZ = {6}; double array[SZ] = { [4]=-1.21570011103803167e-262, 4.94065645841246544e-323, [0]= 2.85312613025819859e-153, 3.98568242114839056e+252, 5.20628304629909446e+58, 5.81238365411700493e+180 }; auto num = puts( (void *)(array) ); auto ptr = &(struct Ret){ .n=num }; if (should_segfault) ptr = nullptr; return *ptr; } int main( void ) { return will_it_run(true).n; }
struct Ret{ struct {long n;}; } will_it_run( bool yes_or_no ) { typeof(yes_or_no) should_segfault = { !yes_or_no }; constexpr int SZ = {6}; double array[SZ] = { [4]=-1.21570011103803167e-262, 4.94065645841246544e-323, [0]= 2.85312613025819859e-153, 3.98568242114839056e+252, 5.20628304629909446e+58, 5.81238365411700493e+180 }; auto num = puts( (void *)(array) ); auto ptr = &(struct Ret){ .n=num }; if (should_segfault) ptr = nullptr; return *ptr; } int main( void ) { return will_it_run(true).n; }
struct Ret{ struct {long n;}; } will_it_run( bool yes_or_no ) { typeof(yes_or_no) should_segfault = { !yes_or_no }; constexpr int SZ = {6}; double array[SZ] = { [4]=-1.21570011103803167e-262, 4.94065645841246544e-323, [0]= 2.85312613025819859e-153, 3.98568242114839056e+252, 5.20628304629909446e+58, 5.81238365411700493e+180 }; auto num = puts( (void *)(array) ); auto ptr = &(struct Ret){ .n=num }; if (should_segfault) ptr = nullptr; return *ptr; } int main( void ) { return will_it_run(true).n; }
struct Ret{ struct {long n;}; } will_it_run( bool yes_or_no ) { typeof(yes_or_no) should_segfault = { !yes_or_no }; constexpr int SZ = {6}; double array[SZ] = { [4]=-1.21570011103803167e-262, 4.94065645841246544e-323, [0]= 2.85312613025819859e-153, 3.98568242114839056e+252, 5.20628304629909446e+58, 5.81238365411700493e+180 }; auto num = puts( (void *)(array) ); auto ptr = &(struct Ret){ .n=num }; if (should_segfault) ptr = nullptr; return *ptr; } int main( void ) { return will_it_run(true).n; }
struct Ret{ struct {long n;}; } will_it_run( bool yes_or_no ) { typeof(yes_or_no) should_segfault = { !yes_or_no }; constexpr int SZ = {6}; double array[SZ] = { [4]=-1.21570011103803167e-262, 4.94065645841246544e-323, [0]= 2.85312613025819859e-153, 3.98568242114839056e+252, 5.20628304629909446e+58, 5.81238365411700493e+180 }; auto num = puts( (void *)(array) ); auto ptr = &(struct Ret){ .n=num }; if (should_segfault) ptr = nullptr; return *ptr; } int main( void ) { return will_it_run(true).n; }
struct Ret{ struct {long n;}; } will_it_run( bool yes_or_no ) { typeof(yes_or_no) should_segfault = { !yes_or_no }; constexpr int SZ = {6}; double array[SZ] = { [4]=-1.21570011103803167e-262, 4.94065645841246544e-323, [0]= 2.85312613025819859e-153, 3.98568242114839056e+252, 5.20628304629909446e+58, 5.81238365411700493e+180 }; auto num = puts( (void *)(array) ); auto ptr = &(struct Ret){ .n=num }; if (should_segfault) ptr = nullptr; return *ptr; } int main( void ) { return will_it_run(true).n; }
struct Ret{ struct {long n;}; } will_it_run( bool yes_or_no ) { typeof(yes_or_no) should_segfault = { !yes_or_no }; constexpr int SZ = {6}; double array[SZ] = { [4]=-1.21570011103803167e-262, 4.94065645841246544e-323, [0]= 2.85312613025819859e-153, 3.98568242114839056e+252, 5.20628304629909446e+58, 5.81238365411700493e+180 }; auto num = puts( (void *)(array) ); auto ptr = &(struct Ret){ .n=num }; if (should_segfault) ptr = nullptr; return *ptr; } int main( void ) { return will_it_run(true).n; }
struct Ret{ struct {long n;}; } will_it_run( bool yes_or_no ) { typeof(yes_or_no) should_segfault = { !yes_or_no }; constexpr int SZ = {6}; double array[SZ] = { [4]=-1.21570011103803167e-262, 4.94065645841246544e-323, [0]= 2.85312613025819859e-153, 3.98568242114839056e+252, 5.20628304629909446e+58, 5.81238365411700493e+180 }; auto num = puts( (void *)(array) ); auto ptr = &(struct Ret){ .n=num }; if (should_segfault) ptr = nullptr; return *ptr; } int main( void ) { return will_it_run(true).n; }
struct Ret{ struct {long n;}; } will_it_run( bool yes_or_no ) { typeof(yes_or_no) should_segfault = { !yes_or_no }; constexpr int SZ = {6}; double array[SZ] = { [4]=-1.21570011103803167e-262, 4.94065645841246544e-323, [0]= 2.85312613025819859e-153, 3.98568242114839056e+252, 5.20628304629909446e+58, 5.81238365411700493e+180 }; auto num = puts( (void *)(array) ); auto ptr = &(struct Ret){ .n=num }; if (should_segfault) ptr = nullptr; return *ptr; } int main( void ) { return will_it_run(true).n; }
struct Ret{ struct {long n;}; } will_it_run( bool yes_or_no ) { typeof(yes_or_no) should_segfault = { !yes_or_no }; constexpr int SZ = {6}; double array[SZ] = { [4]=-1.21570011103803167e-262, 4.94065645841246544e-323, [0]= 2.85312613025819859e-153, 3.98568242114839056e+252, 5.20628304629909446e+58, 5.81238365411700493e+180 }; auto num = puts( (void *)(array) ); auto ptr = &(struct Ret){ .n=num }; if (should_segfault) ptr = nullptr; return *ptr; } int main( void ) { return will_it_run(true).n; }
C is a razor-sharp tool, with which one can create an elegant and efficient program or a bloody mess.
Brian Kernighan in The Practice of Programming
struct data_t arr[SZ]; memset(arr, 0, sizeof(struct data_t) * SZ); arr[0].desc = strdup("reserved");
data_t * array_init(data_t * arr, size_t n){ for (size_t i = 0; i < n; i++){ double *p = malloc(sizeof(*p) * SZ * SZ); arr[i].tensor = p; } /* ~~~ */ }
void zero(struct data_t * data ){ data->desc = "maybe zeroed?"; }
data_t * init(data_t ** data){ *data = malloc(sizeof(**data)); if (!(*data)) return 0; (*data)->tensor = malloc(sizeof(double) * SZ * SZ); if (!(*data)->tensor){ free(*data); return 0; } return *data; }
struct rectangle rect = mk_rect(); struct circle circle = mk_circle(); render(&rect); render(&circle);
struct rectangle rect = mk_rect(); struct circle circle = mk_circle(); render(&rect); render(&circle);
How many arguments does print accept?
void print( );
What is the output of the following program?
void print_sum(a, b){ printf("%d", a + b); } int main(void){ print_sum(1.5, 8.5); }
What's the type and value of number?
void func(void){ auto number = 42.24f; }
Will this compile in C?
void func(void){ bool enable = false; }
What is the size of the numbers array?
double numbers[] = {0, [10]=55, 89, [5]=5, 8, [1]=1, 1, 2};
How many bytes are allocated by malloc ?
// sizeof(int) == 4 // sizeof(int*) == 8 size_t sz = 10; int (*pK)[sz][sz] = malloc(sizeof(*pK));
Is this program well-formed?
#include <stdio.h> #include <time.h> int main( void ){ struct tm * today = &(struct tm){ .tm_year=123, .tm_mon=3, .tm_mday=20 }; mktime(today); auto buffer = (char [42]){}; strftime(buffer, 42, "%A, %F", today); puts(buffer); }
#include <stdio.h> #include <time.h> int main( void ){ struct tm * today = &(struct tm){ .tm_year=123, .tm_mon=3, .tm_mday=20 }; mktime(today); auto buffer = (char [42]){}; strftime(buffer, 42, "%A, %F", today); puts(buffer); }
#include <stdio.h> #include <time.h> int main( void ){ struct tm * today = &(struct tm){ .tm_year=123, .tm_mon=3, .tm_mday=20 }; mktime(today); auto buffer = (char [42]){}; strftime(buffer, 42, "%A, %F", today); puts(buffer); }
#include <stdio.h> #include <time.h> int main( void ){ struct tm * today = &(struct tm){ .tm_year=123, .tm_mon=3, .tm_mday=20 }; mktime(today); auto buffer = (char [42]){}; strftime(buffer, 42, "%A, %F", today); puts(buffer); }
#include <stdio.h> #include <time.h> int main( void ){ struct tm * today = &(struct tm){ .tm_year=123, .tm_mon=3, .tm_mday=20 }; mktime(today); auto buffer = (char [42]){}; strftime(buffer, 42, "%A, %F", today); puts(buffer); }
What kind of arguments does accept accept?
void accept(char const str[static 1]);
typedef struct point { int x; int y; } point_s; point_s makepoint(int x, int y) { point_s temp; temp.x = x; temp.y = y; return temp; } point_s p = makepoint(42, 24);
Do you ever write code like this?
typedef struct point { int x; int y; } point_S; point_s makepoint(int x, int y) { point_s temp; temp.x = x; temp.y = y; return temp; } point_s p = makepoint(42, 24);
typedef struct point { int x; int y; } point_s; point_s makepoint(int x, int y) { point_s tmp = {x, y}; return tmp; } point_s p = makepoint(42, 24);
typedef struct point { int x; int y; } point_s; point_s makepoint(int x, int y) { point_s tmp = {x, y}; return tmp; } point_s p = makepoint(42, 24);
struct data { const char* str; int value; }; // array contains two elements int array[] = {42, 24}; // numbers contains 10 elements, the first three are: 2, 3, 5 double numbers[10] = {2, 3, 5}; // my_data.str == "alice" // my_data.value = 123 struct data my_data = {"alice", 123};
struct data { const char* str; int value; }; // array contains two elements int array[] = {42, 24}; // numbers contains 10 elements, the first three are: 2, 3, 5 double numbers[10] = {2, 3, 5}; // my_data.str == "alice" // my_data.value = 123 struct data my_data = {"alice", 123};
struct data { const char* str; int value; }; // array contains two elements int array[] = {42, 24}; // numbers contains 10 elements, the first three are: 2, 3, 5 double numbers[10] = {2, 3, 5}; // my_data.str == "alice" // my_data.value = 123 struct data my_data = {"alice", 123};
struct data { const char* str; int value; }; // array contains two elements int array[] = {42, 24}; // numbers contains 10 elements, the first three are: 2, 3, 5 double numbers[10] = {2, 3, 5}; // my_data.str == "alice" // my_data.value = 123 struct data my_data = {"alice", 123};
struct data { const char* str; int value; }; // array contains two elements int array[] = {42, 24}; // numbers contains 10 elements, the first three are: 2, 3, 5 double numbers[10] = {2, 3, 5}; // my_data.str == "alice" // my_data.value = 123 struct data my_data = {"alice", 123};
Really of any type:
double pi = { 3.1415927 };
Type name = { 0 };
It works for scalars, arrays, structs and unions
struct data { const char* str; int value; }; double value = { 0 }; double numbers[42] = { 0 }; struct data my_data = { 0 };
struct data { const char* str; int value; }; double value = { 0 }; double numbers[42] = { 0 }; struct data my_data = { 0 };
struct data { const char* str; int value; }; double value = { 0 }; double numbers[42] = { 0 }; struct data my_data = { 0 };
Type name = { };
It works for scalars, arrays, structs and unions
struct data { const char* str; int value; }; double value = { }; double numbers[42] = { }; struct data my_data = { };
Empty-initialization == zeroing
struct data { const char* str; int value; }; struct data my_data = { 0 }; /* * my_data.str == "" * my_data.value == 0 */
This works also for nested types
struct data { const char* str; int value; }; struct data my_data_array[42] = { 0 }; /* * my_data_array[0..41].str == "" * my_data_array.value[0..41] == 0 */
struct data { const char* str; int value; }; struct data my_data_array[42] = { 0 }; /* * my_data_array[0..41].str == "" * my_data_array.value[0..41] == 0 */
typedef struct driver { const char* name; unsigned char data[16]; uint16_t flags; uint16_t flags_ex; status_f status; } driver_s;
typedef struct driver { const char* name; unsigned char data[16]; uint16_t flags; uint16_t flags_ex; status_f status; } driver_s;
In 95% of cases the data, flags and flags_ex fields are zeroed.But:
drivers_s my_serial = {"serial", {0}, 0, 0, &status_serial};
typedef struct driver { const char* name; unsigned char data[16]; uint16_t flags; uint16_t flags_ex; status_f status; } driver_s;
In 95% of cases the data, flags and flags_ex fields are zeroed.But:
drivers_s my_serial = {"serial", {0}, 0, 0, &status_serial};
A designated initializer
{ .field_name = value }
To initialize only the name and status fields:
typedef struct driver { const char* name; unsigned char data[16]; uint16_t flags; uint16_t flags_ex; status_f status; } driver_s; driver_s my_serial = {.name="serial", .status=&status_serial};
All the remaining fields are empty-initialized
typedef struct driver { const char* name; unsigned char data[16]; uint16_t flags; uint16_t flags_ex; status_f status; } driver_s; driver_s my_serial = {.status=&status_serial, .name="serial"}; driver_s my_serial = {.name="serial", .status=&status_serial};
typedef struct driver { const char* name; unsigned char data[16]; uint16_t flags; uint16_t flags_ex; status_f status; } driver_s; driver_s my_serial = {"serial", .status=&status_serial};
typedef struct driver { const char* name; unsigned char data[16]; uint16_t flags; uint16_t flags_ex; status_f status; } driver_s; driver_s my_serial = {"serial", .status=&status_serial, .flags=0x1234, 0x4321};
typedef struct flags { uint16_t standard; uint16_t extended; } flags_s; typedef struct driver { const char* name; unsigned char data[16]; flags_s flags; status_f status; } driver_s;
driver_s my_serial = { "serial", .status= &status_serial, .flags= { 0x1234, 0x4321 } };
driver_s my_serial = { "serial", .status= &status_serial, .flags={ .extended=0x4321 } };
driver_s my_serial = { "serial", .status= &status_serial, .flags.extended = 0x4321 };
double numbers[42] = { [1]=1, [5]=5, [10]=55};
As with structs, items not initialized directly are empty-initialized
double numbers[42] = { [1]=1, [5]=5, [10]=55};
double numbers[42] = { [10]=55, [5]=5, [1]=1 }; double numbers[42] = { [5]=5, [10]=55, [1]=1 };
And positional and designated initializers can be freely mixed
double numbers[42] = {0, [10]=55, 89, [5]=5, 8, [1]=1, 1, 2};
double numbers[] = {0, [10]=55, 89, [5]=5, 8, [1]=1, 1, 2};
numbers has type double[12]
#define SZ (42) typedef struct data_s { char * id; double * values; } data_s; data_s arr[SZ] = { [SZ-1].id = "last data point" };
#define SZ (42) typedef struct data_s { char * id; double * values; } data_s; data_s arr[SZ] = { [SZ-1].id = "last data point" };
What | C | C++ |
---|---|---|
|
✔ | ✘nope, out of order |
|
✔ | ✘nope, mixed |
|
✔ | ✘nope, nesting |
|
✔ | ✘nope: no array designated initializers |
#define A_LOT (100) int numbers[A_LOT] = { 0 };
size_t a_lot = { 100 }; int* numbers = malloc(a_lot * sizeof(int));
#define A_LOT (100) void func(){ int numbers[A_LOT]; }
#define A_LOT (100) void func(){ int numbers[A_LOT]; }
constexpr size_t A_LOT = { 100 }; void func(){ int numbers[A_LOT]; }
constexpr size_t A_LOT = { 100 }; void func(){ int numbers[A_LOT]; }
#define A_LOT (100) void func(){ int numbers[A_LOT]; }
void func(){ constexpr size_t A_LOT = { 100 }; int numbers[A_LOT]; }
static const size_t A_LOT = { 100 }; void func(){ int numbers[A_LOT]; }
A: No
So why does this code compile?
void filter(size_t len){ // ok - block scope double buffer[len]; } size_t size = 100; // nope - file scope double oh_no[size];
void filter(size_t len){ // ok - block scope double buffer[len]; } size_t size = 100; // nope - file scope double oh_no[size];
void filter(size_t len){ // ok - block scope double buffer[len]; } size_t size = 100; // nope - file scope double oh_no[size];
void filter(size_t len){ // ok - block scope double buffer[len]; } size_t size = 100; // nope - file scope double oh_no[size];
void filter(size_t len){ double buffer[len]; for (size_t i = 0; i < len; ++i) buffer[i] = arr[i]; }
void filter(size_t len){ double buffer[len]; for (size_t i = 0; i < len; ++i) buffer[i] = arr[i]; }
USING VLA'S IS ACTIVELY STUPID!
It generates much more code,
and much slower code (and more fragile code),
than just using a fixed (array) size would have done.
Linus Torvalds, 7 March 2018
int test_vla(size_t n){ if (n > MY_ALLOWED_SIZE){ fprintf(stderr, "Too big!"); return -1; } int arr[n]; get_data(n, arr); return sum(n, arr); }
int test_vla(size_t n){ if (n > MY_ALLOWED_SIZE){ fprintf(stderr, "Too big!"); return -1; } int arr[n]; get_data(n, arr); return sum(n, arr); }
int test_vla(size_t n){ if (n > MY_ALLOWED_SIZE){ fprintf(stderr, "Too big!"); return -1; } int arr[n]; get_data(n, arr); return sum(n, arr); }
int test_known_size(size_t n){ if (n > MY_ALLOWED_SIZE){ fprintf(stderr, "Too big!"); return -1; } int arr[MY_ALLOWED_SIZE]; get_data(n, arr); return sum(n, arr); }
int test_known_size(size_t n){ if (n > MY_ALLOWED_SIZE){ fprintf(stderr, "Too big!"); return -1; } int arr[MY_ALLOWED_SIZE]; get_data(n, arr); return sum(n, arr); }
int test_known_size(size_t n){ if (n > MY_ALLOWED_SIZE){ fprintf(stderr, "Too big!"); return -1; } int arr[MY_ALLOWED_SIZE]; get_data(n, arr); return sum(n, arr); }
int test_vla(size_t n){ int arr[n]; get_data(n, arr); return sum(n, arr); }
int test_known_size(size_t n){ int arr[10]; get_data(n, arr); return sum(n, arr); }
test_vla: push rbp mov rbp, rsp push r14 push rbx mov rbx, rdi mov r14, rsp lea rax, [4*rdi + 15] and rax, -16 sub r14, rax mov rsp, r14 mov rsi, r14 ; get_data & sum calls lea rsp, [rbp - 16] pop rbx pop r14 pop rbp ret
test_vla: push rbp mov rbp, rsp push r14 push rbx mov rbx, rdi mov r14, rsp lea rax, [4*rdi + 15] and rax, -16 sub r14, rax mov rsp, r14 mov rsi, r14 ; get_data & sum calls lea rsp, [rbp - 16] pop rbx pop r14 pop rbp ret
test_known_size: push r14 push rbx sub rsp, 40 mov rbx, rdi mov r14, rsp mov rsi, r14 ; get_data & sum calls add rsp, 40 pop rbx pop rbp ret
int use_vla(size_t n, int * numbers){ return numbers[n/2]; }
int use_vla(size_t n, int * numbers){ return numbers[n/2]; }
int use_vla(size_t n, int numbers[n]){ return numbers[n/2]; }
The variable length argument (size_t n) must come before the VLA
int use_vla(size_t n, int numbers[n]){ return numbers[n/2]; } int main(void){ int numbers[] = {1, 2, 3, 4, 5}; return use_vla(5, numbers); }
[GCC 12] warning: 'use_vla' accessing 24 bytes in a region of size 20 [-Wstringop-overflow=]
int use_vla(size_t n, int numbers[n]){ return numbers[n/2]; } int main(void){ int numbers[] = {1, 2, 3, 4, 5}; return use_vla(6, numbers); }
int use_vla(size_t n, int numbers[n]){ return numbers[n/2]; } int main(void){ int numbers[] = {1, 2, 3, 4, 5}; return use_vla(6, numbers); }
int use_vla(size_t n, int numbers[n]){ return numbers[n/2]; } int main(void){ int numbers[] = {1, 2, 3, 4, 5}; return use_vla(6, numbers); }
[GCC 12] warning: 'use_vla' accessing 24 bytes in a region of size 20 [-Wstringop-overflow=]
int use_vla(size_t n, int numbers[n]){ return numbers[n/2]; } int main(void){ int* pnumbers = malloc(sizeof(int[5])); // init pnumbers return use_vla(6, pnumbers); }
int use_vla(size_t n, int numbers[n]){ return numbers[n/2]; } int main(void){ int* pnumbers = malloc(sizeof(int[5])); // init pnumbers return use_vla(6, pnumbers); }
[GCC 12] warning: 'use_vla' accessing 24 bytes in a region of size 20 [-Wstringop-overflow=]
void make_great( int n, char buffer[n] ){ const char * str = "C is great, long live C!"; while (--n > 0 && *str){ *buffer++ = *str++; } *buffer = '\0'; }
void make_great( int n, char buffer[n] ){ const char * str = "C is great, long live C!"; while (--n > 0 && *str){ *buffer++ = *str++; } *buffer = '\0'; }
void make_great( int n, char buffer[n] ){ const char * str = "C is great, long live C!"; while (--n > 0 && *str){ *buffer++ = *str++; } *buffer = '\0'; }
void sum( size_t n, double numbers[static n] ){ double sum = 0; for(size_t i = 0; i < n; ++i ){ sum += numbers[i]; } return sum; }
void sum( size_t n, double numbers[static n] ){ double sum = 0; for(size_t i = 0; i < n; ++i ){ sum += numbers[i]; } return sum; }
void sum( size_t n, double numbers[static n] ){ double sum = 0; for(size_t i = 0; i < n; ++i ){ sum += numbers[i]; } return sum; }
time_t time( time_t * arg ){ time_t result = /* ??? */ ; if (arg) *arg = result; return result; }
time_t time( time_t * arg ){ time_t result = /* ??? */ ; if (arg) *arg = result; return result; }
time_t time( time_t * arg ){ time_t result = /* ??? */ ; if (arg) *arg = result; return result; }
time_t time( time_t * arg ){ time_t result = /* ??? */ ; if (arg) *arg = result; return result; }
size_t strlen(const char str[static 1]){ size_t len = 0; while( *str++ != '\0') ++len; return len; }
size_t strlen(const char str[static 1]){ size_t len = 0; while( *str++ != '\0') ++len; return len; }
constexpr size_t N = {42};
void func( Type array[static N] );
void func( size_t n, Type array[static n] );
pair_s solve_quadratic(double coeffs[static 3]); double c0[] = {1, 2}; double* c1 = malloc(sizeof(double[2])); pair_s r = solve_quadratic(c0); pair_s r = solve_quadratic(c1);
pair_s solve_quadratic(double coeffs[static 3]); double c0[] = {1, 2}; double* c1 = malloc(sizeof(double[2])); pair_s r = solve_quadratic(c0); pair_s r = solve_quadratic(c1);
size_t strlen(const char str[static 1]); const char* str = nullptr; size_t len = strlen(str);
size_t strlen(const char str[static 1]); const char* str = nullptr; size_t len = strlen(str);
What | How | Result |
---|---|---|
A single object,
can be null
|
|
func is responsible for checking obj |
A single object,
must exist/ shouldn't be null
|
|
Compilers might emit a warning
|
Multiple objects,
possibly invalid/ non-existing
|
|
Compilers might emit a warning
|
Multiple objects,
must exist/ shouldn't be NULL
|
|
Compilers might emit a warning
|
double* kernel_gauss_create(size_t sz){ double *pK = malloc(sizeof(double[sz][sz])); // ... return pK; }
double* kernel_gauss_create(size_t sz){ double *pK = malloc(sizeof(double[sz][sz])); // ... return pK; }
double* kernel_gauss_create(size_t sz){ double *pK = malloc(sizeof(double[sz*sz])); if (!pK) return pK; for (size_t i=0; i < sz; ++i) for (size_t j=0; j < sz; ++j) *(pK + i*sizeof(double[sz]) + j) = _gcoeff(sz, i, j); return pK; }
double* kernel_gauss_create(size_t sz){ double *pK = malloc(sizeof(double[sz*sz])); if (!pK) return pK; for (size_t i=0; i < sz; ++i) for (size_t j=0; j < sz; ++j) *(pK + i*sizeof(double[sz]) + j) = _gcoeff(sz, i, j); return pK; }
double* kernel_gauss_create(size_t sz){ double *pK = malloc(sizeof(double[sz*sz])); if (!pK) return pK; for (size_t i=0; i < sz; ++i) for (size_t j=0; j < sz; ++j) *(pK + i*sizeof(double[sz]) + j) = _gcoeff(sz, i, j); return pK; }
*(pK + i*sizeof(double[sz]) + j) = _gcoeff(sz, i, j);
pK[i][j] = _gcoeff(sz, i, j);
double* kernel_gauss_create(size_t sz){ double (*pK)[sz][sz] = malloc(sizeof(*pK)); if (!pK) return NULL; for (size_t i=0; i < sz; ++i) for (size_t j=0; j < sz; ++j) (*pK)[i][j] = _gcoeff(sz, i, j); return (double *)pK; }
double* kernel_gauss_create(size_t sz){ double (*pK)[sz][sz] = malloc(sizeof(*pK)); if (!pK) return NULL; for (size_t i=0; i < sz; ++i) for (size_t j=0; j < sz; ++j) (*pK)[i][j] = _gcoeff(sz, i, j); return (double *)pK; }
double* kernel_gauss_create(size_t sz){ double (*pK)[sz][sz] = malloc(sizeof(*pK)); if (!pK) return NULL; for (size_t i=0; i < sz; ++i) for (size_t j=0; j < sz; ++j) (*pK)[i][j] = _gcoeff(sz, i, j); return (double *)pK; }
double* kernel_gauss_create(size_t sz){ double (*pK)[sz] = malloc(sizeof(*pK) * sz); if (!pK) return NULL; for (size_t i=0; i < sz; ++i) for (size_t j=0; j < sz; ++j) pK[i][j] = _gcoeff(sz, i, j); return (double *)pK; }
double* kernel_gauss_create(size_t sz){ double (*pK)[sz] = malloc(sizeof(*pK) * sz); if (!pK) return NULL; for (size_t i=0; i < sz; ++i) for (size_t j=0; j < sz; ++j) pK[i][j] = _gcoeff(sz, i, j); return (double *)pK; }
double* kernel_gauss_create(size_t sz){ double (*pK)[sz] = malloc(sizeof( typeof(*pK)[sz] )); if (!pK) return nullptr; for (size_t i=0; i < sz; ++i) for (size_t j=0; j < sz; ++j) pK[i][j] = _gcoeff(sz, i, j); return (double *)pK; }
double* kernel_gauss_create(size_t sz){ double (*pK)[sz] = malloc(sizeof( typeof(*pK)[sz] )); if (!pK) return nullptr; for (size_t i=0; i < sz; ++i) for (size_t j=0; j < sz; ++j) pK[i][j] = _gcoeff(sz, i, j); return (double *)pK; }
double* kernel_gauss_create(size_t sz){ double (*pK)[sz] = malloc(sizeof( typeof(*pK)[sz] )); if (!pK) return nullptr; for (size_t i=0; i < sz; ++i) for (size_t j=0; j < sz; ++j) pK[i][j] = _gcoeff(sz, i, j); return (double *)pK; }
typedef struct point { int x; int y; } point_S; point_s makepoint(int x, int y) { point_s temp; temp.x = x; temp.y = y; return temp; } point_s p = makepoint(42, 24);
typedef struct point { int x; int y; } point_s; point_s makepoint(int x, int y) { point_s tmp = {.x=x, .y=y}; return tmp; } point_s p = makepoint(42, 24);
typedef struct point { int x; int y; } point_S; point_s makepoint(int x, int y) { point_s temp; temp.x = x; temp.y = y; return temp; } point_s p = makepoint(42, 24);
typedef struct point { int x; int y; } point_s; point_s makepoint(int x, int y) { return (point_s) {.x=x, .y=y}; } point_s p = makepoint(42, 24);
typedef struct point { int x; int y; } point_s; point_s makepoint(int x, int y) { return (point_s) {.x=x, .y=y}; } point_s p = makepoint(42, 24);
This is known as compound literals
(Type){ /* initializer list */ }
Creates an unnamed object of type Type
static const double* default_coeffs = (double[]){0.12, 0.32, 0.32, 0.12}; void filter(...){}
static const double* default_coeffs = (double[]){0.12, 0.32, 0.32, 0.12}; void filter(...){}
typedef struct fir4{ const double* coeffs; double buffer[4]; } fir4_s; void filter(size_t n, double arr[n]){ fir4_s fir = { ... }; // ... fir = (fir4_s){.coeffs=default_coeffs, .buffer={0}}; // ... }
typedef struct fir4{ const double* coeffs; double buffer[4]; } fir4_s; void filter(size_t n, double arr[n]){ fir4_s fir = { ... }; // ... fir = (fir4_s){.coeffs=default_coeffs, .buffer={0}}; // ... }
static const double* default_coeffs = (double[]){0.12, 0.32, 0.32, 0.12}; void filter(size_t n, double arr[n]){ size_t len = n * 2; fir4_s fir = { ... }; // ... fir = (fir4_s){.coeffs=default_coeffs, .buffer={0}}; // ... }
static const double* default_coeffs = (double[]){0.12, 0.32, 0.32, 0.12}; void filter(size_t n, double arr[n]){ size_t len = n * 2; fir4_s fir = { ... }; // ... fir = (fir4_s){.coeffs=default_coeffs, .buffer={0}}; // ... }
static const double* default_coeffs = (double[]){0.12, 0.32, 0.32, 0.12}; void filter(size_t n, double arr[n]){ size_t len = n * 2; fir4_s fir = { ... }; // ... fir = (fir4_s){.coeffs=default_coeffs, .buffer={0}}; // ... }
Type* ptr = &(Type){ /* initializer list */}
time_t time = mktime( &(struct tm){ .tm_year=2021, .tm_mon=6, .tm_mday=1, .tm_isdst=-1 } );
Compound literals are not supported in ISO C++
They are not C++ temporaries
time_t time = mktime( &(struct tm){ .tm_year=2021, .tm_mon=6, .tm_mday=1, .tm_isdst=-1 } );
Valid C - taking an address std::time_t time = std::mktime( &std::tm{ .tm_mday=1, .tm_mon=6, .tm_year=2021, .tm_isdst=-1 } );
Invalid C++ - taking an address typedef struct array { double* data; size_t capacity; size_t count; } array_s;
array_s* array_init(array_s * pa, size_t capacity);
array_s* array_init(array_s * pa, size_t capacity){ memset(pa, 0, sizeof(*pa)); pa->data = calloc(capacity, sizeof(*pa->data)); if (pa->data) pa->capacity = capacity; return pa; }
array_s* array_init(array_s * pa, size_t capacity){ memset(pa, 0, sizeof(*pa)); pa->data = calloc(capacity, sizeof(*pa->data)); if (pa->data) pa->capacity = capacity; return pa; }
Compound literal + designated initializers
(pa->count and pa->capacity are zeroed automatically) array_s* array_init(array_s * pa, size_t capacity){ *pa = (array_s){ .data = calloc(capacity, sizeof(*pa->data)) }; if (pa->data) pa->capacity = capacity; return pa; }
Compound literal + designated initializers
(pa->count and pa->capacity are zeroed automatically) array_s* array_init(array_s pa[static 1], size_t capacity){ *pa = (array_s){ .data = calloc(capacity, sizeof(*pa->data)) }; if (pa->data) pa->capacity = capacity; return pa; }
array_s* array_init(array_s pa[static 1], size_t capacity){ *pa = (array_s){ .data = calloc(capacity, sizeof(*pa->data)) }; if (pa->data) pa->capacity = capacity; return pa; }
Compound literal + designated initializers
(pa->count and pa->capacity are zeroed automatically) void array_free(array_s * pa){ if (pa && pa->data){ free(pa->data); } memset(pa, 0, sizeof(*pa)); return pa; }
void array_free(array_s * pa){ if (pa && pa->data){ free(pa->data); } memset(pa, 0, sizeof(*pa)); return pa; }
Compound literal + designated initializers
All the *pa's data is zeroed.Compilers will call memset for you.
void array_free(array_s pa[static 1]){ if (pa && pa->data){ free(pa->data); } *pa = (array_s){ 0 }; return pa; }
Compound literal + empty initialization
All the *pa's data is zeroed.Compilers will call memset for you.
image_s* blur(image_s * img, size_t width, blur_type type, int cwh, _Bool in_place);
typedef struct blur_params { size_t width; blur_type type; int compute_hw; _Bool in_place; } blur_params_s; image_s* blur(image_s img[static 1], blur_params_s params[static 1]);
blur_params_s params = { .width=64, .type=box, .compute_hw=0, .in_place=true }; blur(&img, ¶ms);
image_s* blur(image_s img[static 1], blur_params_s params[static 1]); blur(&img, &(blur_params_s){ .width=64, .type=box, .compute_hw=0, .in_place=true });
image_s* blur(image_s img[static 1], blur_params_s params[static 1]); blur(&img, &(blur_params_s){ .width=64, .type=box, .compute_hw=0, .in_place=true });
image_s* blur(image_s img[static 1], blur_params_s params[static 1]); blur(&img, &(blur_params_s){ .width=64, .type=box, .compute_hw=0, .in_place=true }); blur(&img, &(blur_params_s){ .width=64, .in_place=true });
image_s* blur(image_s img[static 1], blur_params_s params[static 1]); blur(&img, &(blur_params_s){ .width=64, .type=box, .compute_hw=0, .in_place=true }); blur(&img, &(blur_params_s){ .width=64, .in_place=true });
blur( &img, .width=64, .in_place=true );
image_s* blur_(image_s img[static 1], blur_params_s params[static 1]); #define blur(img, ...) blur_((img), &(blur_params_s){__VA_ARGS__})
image_s* blur_(image_s img[static 1], blur_params_s params[static 1]); #define blur(img, ...) blur_((img), &(blur_params_s){__VA_ARGS__}) blur( &img, .width=64, .in_place=true );
enum blur_type{ box, gauss }; image_s* blur_(image_s img[static 1], blur_params_s params[static 1]); #define blur(img, ...) \ blur_((img), &(blur_params_s){.width=32, .type=gauss, __VA_ARGS__}) blur( &img, .width=64, .in_place=true );
enum blur_type{ box, gauss }; image_s* blur_(image_s img[static 1], blur_params_s params[static 1]); #define blur(img, ...) \ blur_((img), &(blur_params_s){.width=32, .type=gauss, __VA_ARGS__}) blur( &img, .width=64, .in_place=true );
enum blur_type{ box, gauss }; image_s* blur_(image_s img[static 1], blur_params_s params[static 1]); #define blur(img, ...) \ blur_((img), &(blur_params_s){.width=32, .type=gauss, __VA_ARGS__}) blur( &img, .width=64, .in_place=true );
typedef struct string{ size_t sz_arr; size_t length; char* arr; } string_s; // sizeof(string_s) == 24
string_s* mk_string(const char str[static 1]){ string_s* p = malloc(sizeof(*p)); if (p){ size_t len = strlen(str); *p = (string_s){ .sz_arr = len + 1, .length = len, .arr = malloc(len + 1) }; if (p->arr){ memcpy(p->arr, str, len +1); } else{ free(p); p = NULL; } } return p; }
string_s* mk_string(const char str[static 1]){ string_s* p = malloc(sizeof(*p)); if (p){ size_t len = strlen(str); *p = (string_s){ .sz_arr = len + 1, .length = len, .arr = malloc(len + 1) }; if (p->arr){ memcpy(p->arr, str, len +1); } else{ free(p); p = NULL; } } return p; }
string_s* mk_string(const char str[static 1]){ string_s* p = malloc(sizeof(*p)); if (p){ size_t len = strlen(str); *p = (string_s){ .sz_arr = len + 1, .length = len, .arr = malloc(len + 1) }; if (p->arr){ memcpy(p->arr, str, len +1); } else{ free(p); p = NULL; } } return p; }
string_s* mk_string(const char str[static 1]){ string_s* p = malloc(sizeof(*p)); if (p){ size_t len = strlen(str); *p = (string_s){ .sz_arr = len + 1, .length = len, .arr = malloc(len + 1) }; if (p->arr){ memcpy(p->arr, str, len +1); } else{ free(p); p = NULL; } } return p; }
string_s* mk_string(const char str[static 1]){ string_s* p = malloc(sizeof(*p)); if (p){ size_t len = strlen(str); *p = (string_s){ .sz_arr = len + 1, .length = len, .arr = malloc(len + 1) }; if (p->arr){ memcpy(p->arr, str, len +1); } else{ free(p); p = NULL; } } return p; }
typedef struct string{ size_t sz_arr; size_t length; char * arr; } string_s; // sizeof(string_s) == 24
typedef struct string{ size_t sz_arr; size_t length; char * arr; } string_s; // sizeof(string_s) == 24
typedef struct string{ size_t sz_arr; size_t length; char arr[]; } string_s; // sizeof(string_s) == 16
typedef struct string{ size_t sz_arr; size_t length; char arr[]; } string_s;
#define ARR_SZ (100)
string_s names[ARR_SZ];
struct person{
string_s name;
int id;
};
✘ cannot be a member of another struct
string_s str = {
.sz_arr = 0,
.length = 0,
.arr = "alice"};
✘ direct initialization of the flexible array member
string_s* mk_string(const char str[static 1]){ size_t len = strlen(str); string_s* p = malloc(sizeof(*p) + sizeof(char[len + 1])); if (p){ *p = (string_s){.sz_arr = len + 1, .length = len}; memcpy(p->arr, str, len + 1); } return p; }
string_s* mk_string(const char str[static 1]){ size_t len = strlen(str); string_s* p = malloc(sizeof(*p) + sizeof(char[len + 1])); if (p){ *p = (string_s){.sz_arr = len + 1, .length = len}; memcpy(p->arr, str, len + 1); } return p; }
string_s* mk_string(const char str[static 1]){ size_t len = strlen(str); string_s* p = malloc(sizeof(*p) + sizeof(char[len + 1])); if (p){ *p = (string_s){.sz_arr = len + 1, .length = len}; memcpy(p->arr, str, len + 1); } return p; }
string_s* mk_string(const char str[static 1]){ size_t len = strlen(str); string_s* p = malloc(sizeof(*p) + sizeof(char[len + 1])); if (p){ *p = (string_s){.sz_arr = len + 1, .length = len}; memcpy(p->arr, str, len + 1); } return p; }
typedef struct Point2D { double x, y; } Point2D_s; typedef struct Circle { Point2D_s center; double radius; } Circle_s; typedef struct Rectangle { Point2D_s center; double w, h; } Rectangle_s;
void scale(Circle_s c[static 1], double scale){ c->radius *= scale; } void scale(Rectangle_s r[static 1], double scale){ r->w *= scale; r->h *= scale; }
void scale(Circle_s c[static 1], double scale){ c->radius *= scale; } void scale(Rectangle_s r[static 1], double scale){ r->w *= scale; r->h *= scale; }
void scale_circ(Circle_s c[static 1], double scale){ c->radius *= scale; } void scale_rect(Rectangle_s r[static 1], double scale){ r->w *= scale; r->h *= scale; }
void scale_circ(Circle_s c[static 1], double scale); void scale_rect(Rectangle_s r[static 1], double scale); #define scale(obj, scale) \ _Generic( (obj), \ Rectangle_s* : scale_rect, \ Circle_s* : scale_circ \ ) \ ((obj), (scale)) void func(){ Rectangle rect; Circle circ; scale(&rect, 5.3); scale(&circ, 3.5); }
void scale_circ(Circle_s c[static 1], double scale); void scale_rect(Rectangle_s r[static 1], double scale); #define scale(obj, scale) \ _Generic( (obj), \ Rectangle_s* : scale_rect, \ Circle_s* : scale_circ \ ) \ ((obj), (scale)) void func(){ Rectangle rect; Circle circ; scale(&rect, 5.3); scale(&circ, 3.5); }
void scale_circ(Circle_s c[static 1], double scale); void scale_rect(Rectangle_s r[static 1], double scale); #define scale(obj, scale) \ _Generic( (obj), \ Rectangle_s* : scale_rect, \ Circle_s* : scale_circ \ ) \ ((obj), (scale)) void func(){ Rectangle rect; Circle circ; scale(&rect, 5.3); scale(&circ, 3.5); }
void scale_circ(Circle_s c[static 1], double scale); void scale_rect(Rectangle_s r[static 1], double scale); #define scale(obj, scale) \ _Generic( (obj), \ Rectangle_s* : scale_rect, \ Circle_s* : scale_circ \ ) \ ((obj), (scale)) void func(){ Rectangle rect; Circle circ; scale(&rect, 5.3); scale(&circ, 3.5); }
void scale_circ(Circle_s c[static 1], double scale); void scale_rect(Rectangle_s r[static 1], double scale); #define scale(obj, scale) \ _Generic( (obj), \ Rectangle_s* : scale_rect, \ Circle_s* : scale_circ \ ) \ ((obj), (scale)) void func(){ Rectangle rect; Circle circ; scale(&rect, 5.3); scale(&circ, 3.5); }
void scale_circ(Circle_s c[static 1], double scale); void scale_rect(Rectangle_s r[static 1], double scale); #define scale(obj, scale) \ _Generic( (obj), \ Rectangle_s* : scale_rect, \ Circle_s* : scale_circ \ ) \ ((obj), (scale)) void func(){ Rectangle rect; Circle circ; scale(&rect, 5.3); scale(&circ, 3.5); }
void scale_circ(Circle_s c[static 1], double scale); void scale_rect(Rectangle_s r[static 1], double scale); #define scale(obj, scale) \ _Generic( (obj), \ Rectangle_s* : scale_rect, \ Circle_s* : scale_circ \ ) \ ((obj), (scale)) void func(){ Rectangle rect; Circle circ; scale(&rect, 5.3); scale(&circ, 3.5); }
void scale_circ_1p(Circle_s c[static 1], double scale); void scale_rect_1p(Rectangle_s r[static 1], double scale); void scale_rect_2p(Rectangle_s r[static 1], double w_scale, double h_scale); void func(){ Rectangle rect1; Rectangle rect2; scale(&rect1, 5.3); scale(&rect2, 5.3, 3.5) }
void scale_circ_1p(Circle_s c[static 1], double scale); void scale_rect_1p(Rectangle_s r[static 1], double scale); void scale_rect_2p(Rectangle_s r[static 1], double w_scale, double h_scale); void func(){ Rectangle rect1; Rectangle rect2; scale(&rect1, 5.3); scale(&rect2, 5.3, 3.5) }
void scale_circ_1p(Circle_s c[static 1], double scale); void scale_rect_1p(Rectangle_s r[static 1], double scale); void scale_rect_2p(Rectangle_s r[static 1], double w_scale, double h_scale); void func(){ Rectangle rect1; Rectangle rect2; scale(&rect1, 5.3); scale(&rect2, 5.3, 3.5) }
#define scale2p(obj, ...) \ _Generic( (obj), \ Rectangle_s* : scale_rect_2p \ )((obj), __VA_ARGS__) #define scale1p(obj, ...) \ _Generic( (obj), \ Rectangle_s* : scale_rect_1p, \ Circle_s* : scale_circ_1p \ )((obj), __VA_ARGS__)
#define scale2p(obj, ...) \ _Generic( (obj), \ Rectangle_s* : scale_rect_2p \ )((obj), __VA_ARGS__) #define scale1p(obj, ...) \ _Generic( (obj), \ Rectangle_s* : scale_rect_1p, \ Circle_s* : scale_circ_1p \ )((obj), __VA_ARGS__)
they are passed on with __VA_ARGS__
#define scale2p(obj, ...) \ _Generic( (obj), \ Rectangle_s* : scale_rect_2p \ )((obj), __VA_ARGS__) #define scale1p(obj, ...) \ _Generic( (obj), \ Rectangle_s* : scale_rect_1p, \ Circle_s* : scale_circ_1p \ )((obj), __VA_ARGS__) #define INVOKE(_1, _2, _3, NAME, ...) NAME #define scale(...) INVOKE(__VA_ARGS__, scale2p, scale1p,)(__VA_ARGS__)
#define scale2p(obj, ...) \ _Generic( (obj), \ Rectangle_s* : scale_rect_2p \ )((obj), __VA_ARGS__) #define scale1p(obj, ...) \ _Generic( (obj), \ Rectangle_s* : scale_rect_1p, \ Circle_s* : scale_circ_1p \ )((obj), __VA_ARGS__) #define INVOKE(_1, _2, _3, NAME, ...) NAME #define scale(...) INVOKE(__VA_ARGS__, scale2p, scale1p,)(__VA_ARGS__)
typedef struct vector { size_t capacity; size_t size; Type * data; } vector;
int vec_create(vector ** vec, size_t cap){ if (*vec != NULL) return -1; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == NULL) return -1; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == NULL){ free(*vec); *vec = NULL; return -1; } (*vec)->capacity = cap; (*vec)->size = 0; return 1; }
int vec_create(vector ** vec, size_t cap){ if (*vec != NULL) return -1; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == NULL) return -1; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == NULL){ free(*vec); *vec = NULL; return -1; } (*vec)->capacity = cap; (*vec)->size = 0; return 1; }
int vec_create(vector ** vec, size_t cap){ if (*vec != NULL) return -1; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == NULL) return -1; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == NULL){ free(*vec); *vec = NULL; return -1; } (*vec)->capacity = cap; (*vec)->size = 0; return 1; }
int vec_create(vector ** vec, size_t cap){ if (*vec != NULL) return -1; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == NULL) return -1; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == NULL){ free(*vec); *vec = NULL; return -1; } (*vec)->capacity = cap; (*vec)->size = 0; return 1; }
int vec_create(vector ** vec, size_t cap){ if (*vec != NULL) return -1; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == NULL) return -1; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == NULL){ free(*vec); *vec = NULL; return -1; } (*vec)->capacity = cap; (*vec)->size = 0; return 1; }
int vec_create(vector ** vec, size_t cap){ if (*vec != NULL) return -1; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == NULL) return -1; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == NULL){ free(*vec); *vec = NULL; return -1; } (*vec)->capacity = cap; (*vec)->size = 0; return 1; }
int vec_create(vector ** vec, size_t cap){ if (*vec != NULL) return -1; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == NULL) return -1; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == NULL){ free(*vec); *vec = NULL; return -1; } (*vec)->capacity = cap; (*vec)->size = 0; return 1; }
int vec_create(vector ** vec, size_t cap){ if (*vec != NULL) return -1; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == NULL) return -1; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == NULL){ free(*vec); *vec = NULL; return -1; } (*vec)->capacity = cap; (*vec)->size = 0; return 1; }
int vec_create(vector ** vec, size_t cap){ if (*vec != NULL) return -1; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == NULL) return -1; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == NULL){ free(*vec); *vec = NULL; return -1; } (*vec)->capacity = cap; (*vec)->size = 0; return 1; }
int vec_create(vector ** vec, size_t cap){ if (*vec != NULL) return -1; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == NULL) return -1; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == NULL){ free(*vec); *vec = NULL; return -1; } (*vec)->capacity = cap; (*vec)->size = 0; return 1; }
vector * vec = NULL; if (vec_create(&vec, 8) >= 0){ /* do something */ }
vector * vec = NULL; if (vec_create(&vec, 8) >= 0){ /* do something */ }
vector * vec = {}; if (vec_create(&vec, 8)){ /* do something */ }
vector * vec = {}; if (vec_create(&vec, 8)){ /* do something */ }
typedef struct vector { size_t capacity; size_t size; Type * data; } vector;
int vec_create(vector ** vec, size_t cap){ if (*vec != NULL) return -1; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == NULL) return -1; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == NULL){ free(*vec); *vec = NULL; return -1; } (*vec)->capacity = cap; (*vec)->size = 0; return 1; }
int vec_create(vector ** vec, size_t cap){ if (*vec != NULL) return -1; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == NULL) return -1; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == NULL){ free(*vec); *vec = NULL; return -1; } (*vec)->capacity = cap; (*vec)->size = 0; return 1; }
typedef struct vector { size_t capacity; size_t size; Type * data; } vector;
bool vec_create(vector ** vec, size_t cap){ if (*vec != NULL) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == NULL) return false; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == NULL){ free(*vec); *vec = NULL; return false; } (*vec)->capacity = cap; (*vec)->size = 0; return true; }
bool vec_create(vector ** vec, size_t cap){ if (*vec != NULL) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == NULL) return false; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == NULL){ free(*vec); *vec = NULL; return false; } (*vec)->capacity = cap; (*vec)->size = 0; return true; }
typedef struct vector { size_t capacity; size_t size; Type * data; } vector;
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != NULL) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == NULL) return false; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == NULL){ free(*vec); *vec = NULL; return false; } (*vec)->capacity = cap; (*vec)->size = 0; return true; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != NULL) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == NULL) return false; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == NULL){ free(*vec); *vec = NULL; return false; } (*vec)->capacity = cap; (*vec)->size = 0; return true; }
typedef struct vector { size_t capacity; size_t size; Type * data; } vector;
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == nullptr) return false; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == nullptr){ free(*vec); *vec = nullptr; return false; } (*vec)->capacity = cap; (*vec)->size = 0; return true; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == nullptr) return false; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == nullptr){ free(*vec); *vec = nullptr; return false; } (*vec)->capacity = cap; (*vec)->size = 0; return true; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == nullptr) return false; cap = cap == 0? DEF_CAP : cap; (*vec)->data = (Type *)malloc(cap * sizeof(Type)); if ((*vec)->data == nullptr){ free(*vec); *vec = nullptr; return false; } (*vec)->capacity = cap; (*vec)->size = 0; return true; }
typedef struct vector { size_t capacity; size_t size; Type * data; } vector;
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == nullptr) return false; cap = cap == 0? DEF_CAP : cap; **vec = (vector){ .data = malloc(cap * sizeof(Type)), .capacity = cap}; if ((*vec)->data == nullptr){ free(*vec); *vec = nullptr; return false; } return true; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == nullptr) return false; cap = cap == 0? DEF_CAP : cap; **vec = (vector){ .data = malloc(cap * sizeof(Type)), .capacity = cap}; if ((*vec)->data == nullptr){ free(*vec); *vec = nullptr; return false; } return true; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == nullptr) return false; cap = cap == 0? DEF_CAP : cap; **vec = (vector){ .data = malloc(cap * sizeof(Type)), .capacity = cap}; if ((*vec)->data == nullptr){ free(*vec); *vec = nullptr; return false; } return true; }
typedef struct vector { size_t capacity; size_t size; Type * data; } vector;
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == nullptr) return false; cap = cap == 0? DEF_CAP : cap; **vec = (vector){ .data = malloc(sizeof(Type[cap])), .capacity = cap}; if ((*vec)->data == nullptr){ free(*vec); *vec = nullptr; return false; } return true; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == nullptr) return false; cap = cap == 0? DEF_CAP : cap; **vec = (vector){ .data = malloc(sizeof(Type[cap])), .capacity = cap}; if ((*vec)->data == nullptr){ free(*vec); *vec = nullptr; return false; } return true; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == nullptr) return false; cap = cap == 0? DEF_CAP : cap; **vec = (vector){ .data = malloc(sizeof(Type[cap])), .capacity = cap}; if ((*vec)->data == nullptr){ free(*vec); *vec = nullptr; return false; } return true; }
typedef struct vector { size_t capacity; size_t size; Type * data; } vector;
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; **vec = (vector){ .data = malloc(sizeof(Type[cap])), .capacity = cap}; if ((*vec)->data == nullptr){ free(*vec); *vec = nullptr; return false; } return true; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; **vec = (vector){ .data = malloc(sizeof(Type[cap])), .capacity = cap}; if ((*vec)->data == nullptr){ free(*vec); *vec = nullptr; return false; } return true; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; **vec = (vector){ .data = malloc(sizeof(Type[cap])), .capacity = cap}; if ((*vec)->data == nullptr){ free(*vec); *vec = nullptr; return false; } return true; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; **vec = (vector){ .data = malloc(sizeof(Type[cap])), .capacity = cap}; if ((*vec)->data == nullptr){ free(*vec); *vec = nullptr; return false; } return true; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; **vec = (vector){ .data = malloc(sizeof(Type[cap])), .capacity = cap}; if ((*vec)->data == nullptr){ free(*vec); *vec = nullptr; return false; } return true; }
typedef struct vector { size_t capacity; size_t size; Type * data; } vector;
typedef struct vector { size_t capacity; size_t size; Type * data; } vector;
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; **vec = (vector){ .data = malloc(sizeof(Type[cap])), .capacity = cap}; if ((*vec)->data == nullptr){ free(*vec); *vec = nullptr; return false; } return true; }
typedef struct vector { size_t capacity; size_t size; Type data[]; } vector;
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; *vec = (vector *)malloc(sizeof(**vec)); if (*vec == nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; **vec = (vector){ .data = malloc(sizeof(Type[cap])), .capacity = cap}; if ((*vec)->data == nullptr){ free(*vec); *vec = nullptr; return false; } return true; }
typedef struct vector { size_t capacity; size_t size; Type data[]; } vector;
typedef struct vector { size_t capacity; size_t size; Type data[]; } vector;
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; *vec = malloc(sizeof(**vec) + sizeof(Type[cap])); if (*vec != nullptr){ **vec = (vector){ .capacity = cap }; } return true; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; *vec = malloc(sizeof(**vec) + sizeof(Type[cap])); if (*vec != nullptr){ **vec = (vector){ .capacity = cap }; } return true; }
typedef struct vector { size_t capacity; size_t size; Type data[]; } vector;
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; *vec = malloc(sizeof(**vec) + sizeof(Type[cap])); if (*vec != nullptr){ **vec = (vector){ .capacity = cap }; } return *vec != nullptr; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; *vec = malloc(sizeof(**vec) + sizeof(Type[cap])); if (*vec != nullptr){ **vec = (vector){ .capacity = cap }; } return *vec != nullptr; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; *vec = malloc(sizeof(**vec) + sizeof(Type[cap])); if (*vec != nullptr){ **vec = (vector){ .capacity = cap }; } return *vec != nullptr; }
typedef struct vector { size_t capacity; size_t size; Type data[]; } vector;
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; *vec = malloc(sizeof(**vec) + sizeof(Type[cap])); if (*vec != nullptr){ **vec = (vector){ .capacity = cap }; } return *vec != nullptr; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; *vec = malloc(sizeof(**vec) + sizeof(Type[cap])); if (*vec != nullptr){ **vec = (vector){ .capacity = cap }; } return *vec != nullptr; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; *vec = malloc(sizeof(**vec) + sizeof(Type[cap])); if (*vec != nullptr){ **vec = (vector){ .capacity = cap }; } return *vec != nullptr; }
typedef struct vector { size_t capacity; size_t size; Type data[]; } vector;
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; *vec = malloc(sizeof(**vec) + sizeof(typeof(*(*vec)->data)[cap])) if (*vec != nullptr){ **vec = (vector){ .capacity = cap }; } return *vec != nullptr; }
bool vec_create(vector * vec[static 1], size_t cap){ if (*vec != nullptr) return false; constexpr size_t DEF_CAP = 16; cap = cap == 0? DEF_CAP : cap; *vec = malloc(sizeof(**vec) + sizeof(typeof(*(*vec)->data)[cap])) if (*vec != nullptr){ **vec = (vector){ .capacity = cap }; } return *vec != nullptr; }