Swapping elements from array of struct faster - c

I have this struct:
typedef struct data{
char name[100], pseudo[100];
int num0, num1, num2, num3, num4;
long int lnum0, lnum1, lnum2, lnum3, lnum4;
double dnum0, dnum1;
}data;
data list[50]
I create an array of this struct and sort them with a quicksort algorithm.
To do that I must swap element using this function:
void swap(data list[], i, j){
data tmp;
tmp.num1 = list[i].num1
list[i].num1 = list[j].num1
list[j].num1 =tmp.num1
//using memmove to avoid overlaping from the strcpy function
memmove(temp.name,list[i].name,strlen(list[i].name));
memmove(list[i].name,list[j].name,strlen(list[j].num1));
memmove(list[j].name,tmp.name,strlen(tmp.name));
}
I have 16 element in my struct, and i have to repeat 16 times this function to swap them all.
My question is : Is there another simpler,faster or nicer way to proceed, or can we optimize this function ?

This is a typical workaround to sort a array with N elements of type T where both N and sizeof(T) are assumed to be large.
Create a temporary array of N pointers to T.
Fill the temporary array with pointers to the elements in your actual array.
Sort the temporary array. (When comparing elements, you have to dereference the pointers. When exchanging elements, you only have to swap single pointers.)
Rearrange the elements in your original array such that they are in the same order as pointed to by the pointers in your temporary array.
Free the temporary array again.
This technique has the advantage that you only have to perform O(N) swaps of T while you might do O(N log(N)) swaps of T*. The downside is that you'll have to allocate the temporary buffer and go through an additional pointer indirection when comparing elements. You'll have to benchmark in order to see whether or not this pays off for your type.
A possible optimization is to allocate the temporary array on the stack as it never outlives the sorting routine. Putting huge arrays on the stack might cause a stack overflow, though, so be careful about the size.

I'm not sure this is what you're looking for, but a simple way to speed up these swaps would be to store pointers to "struct data" in "list", rather than storing the entire structs themselves. That way when you swap, you only swap 4 or 8 bytes at a time (for 32-bit and 64-bit respectively), instead of a whopping 256 bytes.
If you're set on storing and swapping all the memory for those structs contiguously, your best bet is to use vector intrinsics (SIMD). Here's a guide for gcc. Here's one for msvc.

If it weren't for the fact that you're asking about optimisation, I'd assume this is a homework task. Homework tasks of the sorting variety don't usually involve optimisation, though. Nonetheless, your institution would've taught you in the real world never to reinvent the wheel unless the benefits outweigh the costs. In this case, they don't.
Imagine if your fastest for x86 code were also slowest for ARM. This is such a common scenario the standard library includes two functions within <stdlib.h>: qsort and bsearch. The odds are, the authors of the standard library have a better idea of how to write, test and tune a sorting algorithm for each platform.
Imagine if every process running at every given time reinvented the wheel, leading to lots of duplicate sorting functions being kept and swapped around in memory... One major benefit to using standard library code is that it can be shared among many processes, leading to less duplicate resource consumption. Less resource consumption also happens to most likely lead to faster code, and in this case sharing this resource between multiple processes is also likely to reduce cache thrashing.
To use qsort and bsearch you first need to define a comparison function. This can be as simple as wrapping strcmp, if you can guarantee that the field to sort based on is in fact a string (i.e. the character sequence ends with a '\0'). The comparison function needs to use the signature int compare(void const *x, void const *y);, for example:
int compare_data_by_name(void const *x, void const *y) {
data const *foo = x, *bar = y;
return strcmp(foo->name, bar->name);
}
Calling qsort(list, sizeof list / sizeof *list, sizeof *list, compare_data_by_name); will sort list.
Calling bsearch(&(data){ .name = "fred" }, list, sizeof list / sizeof *list, sizeof *list, compare_data_by_name); will retrieve an item with "fred" as the name.

Related

Is it good programming practice in C to use first array element as array length?

Because in C the array length has to be stated when the array is defined, would it be acceptable practice to use the first element as the length, e.g.
int arr[9]={9,0,1,2,3,4,5,6,7};
Then use a function such as this to process the array:
int printarr(int *ARR) {
for (int i=1; i<ARR[0]; i++) {
printf("%d ", ARR[i]);
}
}
I can see no problem with this but would prefer to check with experienced C programmers first. I would be the only one using the code.
Well, it's bad in the sense that you have an array where the elements does not mean the same thing. Storing metadata with the data is not a good thing. Just to extrapolate your idea a little bit. We could use the first element to denote the element size and then the second for the length. Try writing a function utilizing both ;)
It's also worth noting that with this method, you will have problems if the array is bigger than the maximum value an element can hold, which for char arrays is a very significant limitation. Sure, you can solve it by using the two first elements. And you can also use casts if you have floating point arrays. But I can guarantee you that you will run into hard traced bugs due to this. Among other things, endianness could cause a lot of issues.
And it would certainly confuse virtually every seasoned C programmer. This is not really a logical argument against the idea as such, but rather a pragmatic one. Even if this was a good idea (which it is not) you would have to have a long conversation with EVERY programmer who will have anything to do with your code.
A reasonable way of achieving the same thing is using a struct.
struct container {
int *arr;
size_t size;
};
int arr[10];
struct container c = { .arr = arr, .size = sizeof arr/sizeof *arr };
But in any situation where I would use something like above, I would probably NOT use arrays. I would use dynamic allocation instead:
const size_t size = 10;
int *arr = malloc(sizeof *arr * size);
if(!arr) { /* Error handling */ }
struct container c = { .arr = arr, .size = size };
However, do be aware that if you init it this way with a pointer instead of an array, you're in for "interesting" results.
You can also use flexible arrays, as Andreas wrote in his answer
In C you can use flexible array members. That is you can write
struct intarray {
size_t count;
int data[]; // flexible array member needs to be last
};
You allocate with
size_t count = 100;
struct intarray *arr = malloc( sizeof(struct intarray) + sizeof(int)*count );
arr->count = count;
That can be done for all types of data.
It makes the use of C-arrays a bit safer (not as safe as the C++ containers, but safer than plain C arrays).
Unforntunately, C++ does not support this idiom in the standard.
Many C++ compilers provide it as extension though, but it is not guarantueed.
On the other hand this C FLA idiom may be more explicit and perhaps more efficient than C++ containers as it does not use an extra indirection and/or need two allocations (think of new vector<int>).
If you stick to C, I think this is a very explicit and readable way of handling variable length arrays with an integrated size.
The only drawback is that the C++ guys do not like it and prefer C++ containers.
It is not bad (I mean it will not invoke undefined behavior or cause other portability issues) when the elements of array are integers, but instead of writing magic number 9 directly you should have it calculate the length of array to avoid typo.
#include <stdio.h>
int main(void) {
int arr[9]={sizeof(arr)/sizeof(*arr),0,1,2,3,4,5,6,7};
for (int i=1; i<arr[0]; i++) {
printf("%d ", arr[i]);
}
return 0;
}
Only a few datatypes are suitable for that kind of hack. Therefore, I would advise against it, as this will lead to inconsistent implementation styles across different types of arrays.
A similar approach is used very often with character buffers where in the beginning of the buffer there is stored its actual length.
Dynamic memory allocation in C also uses this approach that is the allocated memory is prefixed with an integer that keeps the size of the allocated memory.
However in general with arrays this approach is not suitable. For example a character array can be much larger than the maximum positive value (127) that can be stored in an object of the type char. Moreover it is difficult to pass a sub-array of such an array to a function. Most of functions that designed to deal with arrays will not work in such a case.
A general approach to declare a function that deals with an array is to declare two parameters. The first one has a pointer type that specifies the initial element of an array or sub-array and the second one specifies the number of elements in the array or sub-array.
Also C allows to declare functions that accepts variable length arrays when their sizes can be specified at run-time.
It is suitable in rather limited circumstances. There are better solutions to the problem it solves.
One problem with it is that if it is not universally applied, then you would have a mix of arrays that used the convention and those that didn't - you have no way of telling if an array uses the convention or not. For arrays used to carry strings for example you have to continually pass &arr[1] in calls to the standard string library, or define a new string library that uses "Pascal strings" rather then "ASCIZ string" conventions (such a library would be more efficient as it happens),
In the case of a true array rather then simply a pointer to memory, sizeof(arr) / sizeof(*arr) will yield the number of elements without having to store it in the array in any case.
It only really works for integer type arrays and for char arrays would limit the length to rather short. It is not practical for arrays of other object types or data structures.
A better solution would be to use a structure:
typedef struct
{
size_t length ;
int* data ;
} intarray_t ;
Then:
int data[9] ;
intarray_t array{ sizeof(data) / sizeof(*data), data } ;
Now you have an array object that can be passed to functions and retain the size information and the data member can be accesses directly for use in third-party or standard library interfaces that do not accept the intarray_t. Moreover the type of the data member can be anything.
Obviously NO is the answer.
All programming languages has predefined functions stored along with the variable type. Why not use them??
In your case is more suitable to access count /length method instead of testing the first value.
An if clause sometimes take more time than a predefined function.
On the first look seems ok to store the counter but imagine you will have to update the array. You will have to do 2 operations, one to insert other to update the counter. So 2 operations means 2 variables to be changed.
For statically arrays might be ok to have them counter then the list, but for dinamic ones NO NO NO.
On the other hand please read programming basic concepts and you will find your idea as a bad one, not complying with programming principles.

In C, how would I choose whether to return a struct or a pointer to a struct?

Working on my C muscle lately and looking through the many libraries I've been working with its certainly gave me a good idea of what is good practice. One thing that I have NOT seen is a function that returns a struct:
something_t make_something() { ... }
From what I've absorbed this is the "right" way of doing this:
something_t *make_something() { ... }
void destroy_something(something_t *object) { ... }
The architecture in code snippet 2 is FAR more popular than snippet 1. So now I ask, why would I ever return a struct directly, as in snippet 1? What differences should I take into account when I'm choosing between the two options?
Furthermore, how does this option compare?
void make_something(something_t *object)
When something_t is small (read: copying it is about as cheap as copying a pointer) and you want it to be stack-allocated by default:
something_t make_something(void);
something_t stack_thing = make_something();
something_t *heap_thing = malloc(sizeof *heap_thing);
*heap_thing = make_something();
When something_t is large or you want it to be heap-allocated:
something_t *make_something(void);
something_t *heap_thing = make_something();
Regardless of the size of something_t, and if you don’t care where it’s allocated:
void make_something(something_t *);
something_t stack_thing;
make_something(&stack_thing);
something_t *heap_thing = malloc(sizeof *heap_thing);
make_something(heap_thing);
This is almost always about ABI stability. Binary stability between versions of the library. In the cases where it is not, it is sometimes about having dynamically sized structs. Rarely it is about extremely large structs or performance.
It is exceedingly rare that allocating a struct on the heap and returning it is nearly as fast as returning it by-value. The struct would have to be huge.
Really, speed is not the reason behind technique 2, return-by-pointer, instead of return-by-value.
Technique 2 exists for ABI stability. If you have a struct and your next version of the library adds another 20 fields to it, consumers of your previous version of the library are binary compatible if they are handed pre-constructed pointers. The extra data beyond the end of the struct they know about is something they don't have to know about.
If you return it on the stack, the caller is allocating the memory for it, and they must agree with you on how big it is. If your library updated since they last rebuilt, you are going to trash the stack.
Technique 2 also permits you to hide extra data both before and after the pointer you return (which versions appending data to the end of the struct is a variant of). You could end the structure with a variable sized array, or prepend the pointer with some extra data, or both.
If you want stack-allocated structs in a stable ABI, almost all functions that talk to the struct need to be passed version information.
So
something_t make_something(unsigned library_version) { ... }
where library_version is used by the library to determine what version of something_t it is expected to return and it changes how much of the stack it manipulates. This isn't possible using standard C, but
void make_something(something_t* here) { ... }
is. In this case, something_t might have a version field as its first element (or a size field), and you would require that it be populated prior to calling make_something.
Other library code taking a something_t would then query the version field to determine what version of something_t they are working with.
As a rule of thumb, you should never pass struct objects by value. In practice, it will be fine to do so as long as they are smaller or equal to the maximum size that your CPU can handle in a single instruction. But stylistically, one typically avoids it even then. If you never pass structs by value you can later on add members to the struct and it won't affect performance.
I think that void make_something(something_t *object) is the most common way to use structures in C. You leave the allocation to the caller. It is efficient but not pretty.
However, object-oriented C programs use something_t *make_something() since they are built with the concept of opaque type, which forces you to use pointers. Whether the returned pointer points at dynamic memory or something else depends on the implementation. OO with opaque type is often one of the most elegant and best ways to design more complex C programs, but sadly, few C programmers know/care about it.
Some pros of the first approach:
Less code to write.
More idiomatic for the use case of returning multiple values.
Works on systems that don't have dynamic allocation.
Probably faster for small or smallish objects.
No memory leak due to forgetting to free.
Some cons:
If the object is large (say, a megabyte) , may cause stack overflow, or may be slow if compilers don't optimize it well.
May surprise people who learned C in the 1970s when this was not possible, and haven't kept up to date.
Does not work with objects that contain a pointer to a part of themself.
I'm somewhat surprised.
The difference is that example 1 creates a structure on the stack, example 2 creates it on the heap. In C, or C++ code which is effectively C, it's idiomatic and convenient to create most objects on the heap. In C++ it is not, mostly they go on the stack. The reason is that if you create an object on the stack, the destructor is called automatically, if you create it on the heap, it must be called explicitly.So it's a lot easier to ensure there are no memory leaks and to handle exceptions is everything goes on the stack. In C, the destructor must be called explictly anyway, and there's no concept of a special destructor function (you have destructors, of course, but they are just normal functions with names like destroy_myobject()).
Now the exception in C++ is for low-level container objects, e.g. vectors, trees, hash maps and so on. These do retain heap members, and they have destructors. Now most memory-heavy objects consist of a few immediate data members giving sizes, ids, tags and so on, and then the rest of the information in STL structures, maybe a vector of pixel data or a map of English word / value pairs. So most of the data is in fact on the heap, even in C++.
And modern C++ is designed so that this pattern
class big
{
std::vector<double> observations; // thousands of observations
int station_x; // a bit of data associated with them
int station_y;
std::string station_name;
}
big retrieveobservations(int a, int b, int c)
{
big answer;
// lots of code to fill in the structure here
return answer;
}
void high_level()
{
big myobservations = retriveobservations(1, 2, 3);
}
Will compile to pretty efficient code. The large observation member won't generate unnecessary makework copies.
Unlike some other languages (like Python), C does not have the concept of a tuple. For example, the following is legal in Python:
def foo():
return 1,2
x,y = foo()
print x, y
The function foo returns two values as a tuple, which are assigned to x and y.
Since C doesn't have the concept of a tuple, it's inconvenient to return multiple values from a function. One way around this is to define a structure to hold the values, and then return the structure, like this:
typedef struct { int x, y; } stPoint;
stPoint foo( void )
{
stPoint point = { 1, 2 };
return point;
}
int main( void )
{
stPoint point = foo();
printf( "%d %d\n", point.x, point.y );
}
This is but one example where you might see a function return a structure.

Triple pointers in C: is it a matter of style?

I feel like triple pointers in C are looked at as "bad". For me, it makes sense to use them at times.
Starting from the basics, the single pointer has two purposes: to create an array, and to allow a function to change its contents (pass by reference):
char *a;
a = malloc...
or
void foo (char *c); //means I'm going to modify the parameter in foo.
{ *c = 'f'; }
char a;
foo(&a);
The double pointer can be a 2D array (or array of arrays, since each "column" or "row" need not be the same length). I personally like to use it when I need to pass a 1D array:
void foo (char **c); //means I'm going to modify the elements of an array in foo.
{ (*c)[0] = 'f'; }
char *a;
a = malloc...
foo(&a);
To me, that helps describe what foo is doing. However, it is not necessary:
void foo (char *c); //am I modifying a char or just passing a char array?
{ c[0] = 'f'; }
char *a;
a = malloc...
foo(a);
will also work.
According to the first answer to this question, if foo were to modify the size of the array, a double pointer would be required.
One can clearly see how a triple pointer (and beyond, really) would be required. In my case if I were passing an array of pointers (or array of arrays), I would use it. Evidently it would be required if you are passing into a function that is changing the size of the multi-dimensional array. Certainly an array of arrays of arrays is not too common, but the other cases are.
So what are some of the conventions out there? Is this really just a question of style/readability combined with the fact that many people have a hard time wrapping their heads around pointers?
Using triple+ pointers is harming both readability and maintainability.
Let's suppose you have a little function declaration here:
void fun(int***);
Hmmm. Is the argument a three-dimensional jagged array, or pointer to two-dimensional jagged array, or pointer to pointer to array (as in, function allocates an array and assigns a pointer to int within a function)
Let's compare this to:
void fun(IntMatrix*);
Surely you can use triple pointers to int to operate on matrices. But that's not what they are. The fact that they're implemented here as triple pointers is irrelevant to the user.
Complicated data structures should be encapsulated. This is one of manifest ideas of Object Oriented Programming. Even in C, you can apply this principle to some extent. Wrap the data structure in a struct (or, very common in C, using "handles", that is, pointers to incomplete type - this idiom will be explained later in the answer).
Let's suppose that you implemented the matrices as jagged arrays of double. Compared to contiguous 2D arrays, they are worse when iterating over them (as they don't belong to a single block of contiguous memory) but allow for accessing with array notation and each row can have different size.
So now the problem is you can't change representations now, as the usage of pointers is hard-wired over user code, and now you're stuck with inferior implementation.
This wouldn't be even a problem if you encapsulated it in a struct.
typedef struct Matrix_
{
double** data;
} Matrix;
double get_element(Matrix* m, int i, int j)
{
return m->data[i][j];
}
simply gets changed to
typedef struct Matrix_
{
int width;
double data[]; //C99 flexible array member
} Matrix;
double get_element(Matrix* m, int i, int j)
{
return m->data[i*m->width+j];
}
The handle technique works like this: in the header file, you declare a incomplete struct and all the functions that work on the pointer to the struct:
// struct declaration with no body.
struct Matrix_;
// optional: allow people to declare the matrix with Matrix* instead of struct Matrix*
typedef struct Matrix_ Matrix;
Matrix* create_matrix(int w, int h);
void destroy_matrix(Matrix* m);
double get_element(Matrix* m, int i, int j);
double set_element(Matrix* m, double value, int i, int j);
in the source file you declare the actual struct and define all the functions:
typedef struct Matrix_
{
int width;
double data[]; //C99 flexible array member
} Matrix;
double get_element(Matrix* m, int i, int j)
{
return m->data[i*m->width+j];
}
/* definition of the rest of the functions */
The rest of the world doesn't know what does the struct Matrix_ contain and it doesn't know the size of it. This means users can't declare the values directly, but only by using pointer to Matrix and the create_matrix function. However, the fact that the user doesn't know the size means the user doesn't depend on it - which means we can remove or add members to struct Matrix_ at will.
Most of the time, the use of 3 levels of indirection is a symptom of bad design decisions made elsewhere in the program. Therefore it is regarded as bad practice and there are jokes about "three star programmers" where, unlike the the rating for restaurants, more stars means worse quality.
The need for 3 levels of indirection often originates from the confusion about how to properly allocate multi-dimensional arrays dynamically. This is often taught incorrectly even in programming books, partially because doing it correctly was burdensome before the C99 standard. My Q&A post Correctly allocating multi-dimensional arrays addresses that very issue and also illustrates how multiple levels of indirection will make the code increasingly hard to read and maintain.
Though as that post explains, there are some situations where a type** might make sense. A variable table of strings with variable length is such an example. And when that need for type** arises, you might soon be tempted to use type***, because you need to return your type** through a function parameter.
Most often this need arises in a situation where you are designing some manner of complex ADT. For example, lets say that we are coding a hash table, where each index is a 'chained' linked list, and each node in the linked list an array. The proper solution then is to re-design the program to use structs instead of multiple levels of indirection. The hash table, linked list and array should be distinct types, autonomous types without any awareness of each other.
So by using proper design, we will avoid the multiple stars automatically.
But as with every rule of good programming practice, there are always exceptions. It is perfectly possible to have a situation like:
Must implement an array of strings.
The number of strings is variable and may change in run-time.
The length of the strings is variable.
You can implement the above as an ADT, but there may also be valid reasons to keep things simple and just use a char* [n]. You then have two options to allocate this dynamically:
char* (*arr_ptr)[n] = malloc( sizeof(char*[n]) );
or
char** ptr_ptr = malloc( sizeof(char*[n]) );
The former is more formally correct, but also cumbersome. Because it has to be used as (*arr_ptr)[i] = "string";, while the alternative can be used as ptr_ptr[i] = "string";.
Now suppose we have to place the malloc call inside a function and the return type is reserved for an error code, as is custom with C APIs. The two alternatives will then look like this:
err_t alloc_arr_ptr (size_t n, char* (**arr)[n])
{
*arr = malloc( sizeof(char*[n]) );
return *arr == NULL ? ERR_ALLOC : OK;
}
or
err_t alloc_ptr_ptr (size_t n, char*** arr)
{
*arr = malloc( sizeof(char*[n]) );
return *arr == NULL ? ERR_ALLOC : OK;
}
It is quite hard to argue and say that the former is more readable, and it also comes with the cumbersome access needed by the caller. The three star alternative is actually more elegant, in this very specific case.
So it does us no good to dismiss 3 levels of indirection dogmatically. But the choice to use them must be well-informed, with an awareness that they may create ugly code and that there are other alternatives.
So what are some of the conventions out there? Is this really just a question of style/readability combined with the fact that many people have a hard time wrapping their heads around pointers?
Multiple indirection is not bad style, nor black magic, and if you're dealing with high-dimension data then you're going to be dealing with high levels of indirection; if you're really dealing with a pointer to a pointer to a pointer to T, then don't be afraid to write T ***p;. Don't hide pointers behind typedefs unless whoever is using the type doesn't have to worry about its "pointer-ness". For example, if you're providing the type as a "handle" that gets passed around in an API, such as:
typedef ... *Handle;
Handle h = NewHandle();
DoSomethingWith( h, some_data );
DoSomethingElseWith( h, more_data );
ReleaseHandle( h );
then sure, typedef away. But if h is ever meant to be dereferenced, such as
printf( "Handle value is %d\n", *h );
then don't typedef it. If your user has to know that h is a pointer to int1 in order to use it properly, then that information should not be hidden behind a typedef.
I will say that in my experience I haven't had to deal with higher levels of indirection; triple indirection has been the highest, and I haven't had to use it more than a couple of times. If you regularly find yourself dealing with >3-dimensional data, then you'll see high levels of indirection, but if you understand how pointer expressions and indirection work it shouldn't be an issue.
1. Or a pointer to pointer to int, or pointer to pointer to pointer to pointer to struct grdlphmp, or whatever.
After two levels of indirection, comprehension becomes difficult. Moreover if the reason you're passing these triple (or more) pointers into your methods is so that they can re-allocate and re-set some pointed-to memory, that gets away from the concept of methods as "functions" that just return values and don't affect state. This also negatively affects comprehension and maintainability beyond some point.
But more fundamentally, you've hit upon one of the main stylistic objections to the triple pointer right here:
One can clearly see how a triple pointer (and beyond, really) would be required.
It's the "and beyond" that is the issue here: once you get to three levels, where do you stop? Surely it's possible to have an aribitrary number of levels of indirection. But it's better to just have a customary limit someplace where comprehensibility is still good but flexibility is adequate. Two's a good number. "Three star programming", as it's sometimes called, is controversial at best; it's either brilliant, or a headache for those who need to maintain the code later.
Unfortunately you misunderstood the concept of pointer and arrays in C. Remember that arrays are not pointers.
Starting from the basics, the single pointer has two purposes: to create an array, and to allow a function to change its contents (pass by reference):
When you declare a pointer, then you need to initialize it before using it in the program. It can be done either by passing address of a variable to it or by dynamic memory allocation.
In latter, pointer can be used as indexed arrays (but it is not an array).
The double pointer can be a 2D array (or array of arrays, since each "column" or "row" need not be the same length). I personally like to use it when I need to pass a 1D array:
Again wrong. Arrays are not pointers and vice-versa. A pointer to pointer is not the 2D array.
I would suggest you to read the c-faq section 6. Arrays and Pointers.

Malloc or normal array definition?

When shall i use malloc instead of normal array definition in C?
I can't understand the difference between:
int a[3]={1,2,3}
int array[sizeof(a)/sizeof(int)]
and:
array=(int *)malloc(sizeof(int)*sizeof(a));
In general, use malloc() when:
the array is too large to be placed on the stack
the lifetime of the array must outlive the scope where it is created
Otherwise, use a stack allocated array.
int a[3]={1,2,3}
int array[sizeof(a)/sizeof(int)]
If used as local variables, both a and array would be allocated on the stack. Stack allocation has its pros and cons:
pro: it is very fast - it only takes one register subtraction operation to create stack space and one register addition operation to reclaim it back
con: stack size is usually limited (and also fixed at link time on Windows)
In both cases the number of elements in each arrays is a compile-time constant: 3 is obviously a constant while sizeof(a)/sizeof(int) can be computed at compile time since both the size of a and the size of int are known at the time when array is declared.
When the number of elements is known only at run-time or when the size of the array is too large to safely fit into the stack space, then heap allocation is used:
array=(int *)malloc(sizeof(int)*sizeof(a));
As already pointed out, this should be malloc(sizeof(a)) since the size of a is already the number of bytes it takes and not the number of elements and thus additional multiplication by sizeof(int) is not necessary.
Heap allocaiton and deallocation is relatively expensive operation (compared to stack allocation) and this should be carefully weighted against the benefits it provides, e.g. in code that gets called multitude of times in tight loops.
Modern C compilers support the C99 version of the C standard that introduces the so-called variable-length arrays (or VLAs) which resemble similar features available in other languages. VLA's size is specified at run-time, like in this case:
void func(int n)
{
int array[n];
...
}
array is still allocated on the stack as if memory for the array has been allocated by a call to alloca(3).
You definately have to use malloc() if you don't want your array to have a fixed size. Depending on what you are trying to do, you might not know in advance how much memory you are going to need for a given task or you might need to dynamically resize your array at runtime, for example you might enlarge it if there is more data coming in. The latter can be done using realloc() without data loss.
Instead of initializing an array as in your original post you should just initialize a pointer to integer like.
int* array; // this variable will just contain the addresse of an integer sized block in memory
int length = 5; // how long do you want your array to be;
array = malloc(sizeof(int) * length); // this allocates the memory needed for your array and sets the pointer created above to first block of that region;
int newLength = 10;
array = realloc(array, sizeof(int) * newLength); // increase the size of the array while leaving its contents intact;
Your code is very strange.
The answer to the question in the title is probably something like "use automatically allocated arrays when you need quite small amounts of data that is short-lived, heap allocations using malloc() for anything else". But it's hard to pin down an exact answer, it depends a lot on the situation.
Not sure why you are showing first an array, then another array that tries to compute its length from the first one, and finally a malloc() call which tries do to the same.
Normally you have an idea of the number of desired elements, rather than an existing array whose size you want to mimic.
The second line is better as:
int array[sizeof a / sizeof *a];
No need to repeat a dependency on the type of a, the above will define array as an array of int with the same number of elements as the array a. Note that this only works if a is indeed an array.
Also, the third line should probably be:
array = malloc(sizeof a);
No need to get too clever (especially since you got it wrong) about the sizeof argument, and no need to cast malloc()'s return value.

Function needs its own array for workspace - best practices?

Suppose that the function
void foo(int n, double x[])
sorts the n-vector x, does some operations on x, and then restores the original ordering to x before returning. So internally, foo needs some temporary storage, e.g., at least an n-vector of integers so that it store the original ordering.
What's the best way to handle this temporary storage? I can think of two obvious approaches:
foo declares its own workspace by declaring an internal array, i.e., at the top of foo we have
int temp[n];
in the main calling routine, dynamically allocate the n-vector of ints once and pass in the storage at each call to a version of foo that accepts the temporary storage as a 3rd arg, i.e.,
double *temp = malloc(n*sizeof(double));
foo(n, x, temp);
I'm worried that option 1 is inefficient (the function foo will get called many times with the same n), and option 2 is just plain ugly, since I have to carry around this temporary storage so that it's always available wherever I happen to need a call to foo(n,x).
Are there other more elegant options?
If you end up using option 2 – that is, the function uses memory that is allocated elsewhere – use proper encapsulation.
In a nutshell, don’t pass in a raw array, pass in a context object which has matching init and release functions.
Then the user must still pass in the context and properly set it up and tear it down but the details are hidden from her and she doesn’t care about the details of the allocation. This is a common pattern in C.
typedef struct {
double* storage;
} foo_context;
void foo_context_init(foo_context*, int n);
void foo_context_free(foo_context*);
void foo(foo_context* context, int n, double x[]);
Now, for a very simple case this is clearly a tremendous overhead and I agree with Oli that option 1 called for.
Option 1 is clearly the cleanest (because it's completely encapsulated). So go with Option 1 until profiling has determined that this is a bottleneck.
Update
#R's comment below is correct; this could blow your stack if n is large. The pre-C99 "encapsulated" method would be to malloc the local array, rather than putting it on the stack.
On most architectures option 1 is very efficient since it allocates memory on the stack and is typically an add to the stack and/or frame pointer. Just be careful not to make n too large.
As Oli said in his answer the best is to have the function being autonomous about this temporary array. A single allocation is not going to cost a lot unless that function is called in a very fast loop... so get it right first, then profile and then decide if it's worth doing an optimization.
That said in a few cases after profiling and when the temp data structure needed was a bit more complex that a single int array I adopted the following approach:
void foo(int n, ... other parameters ...)
{
static int *temp_array, temp_array_size;
if (n > temp_array_size)
{
/* The temp array we have is not big enough, increase it */
temp_array = realloc(temp_array, n*sizeof(int));
if (!temp_array) abort("Out of memory");
temp_array_size = n;
}
... use temp_array ...
}
note that using a static array rules out for example multithreading or recursion and this should be clearly stated in the documentation.

Resources