Don't freak out about the length of my post, it's pretty simple, I just don't know how to put it any shorter:
I have two ways of doing something pretty much similar to merging two arrays via a function. Here I call the function combine_data()
. The arrays are called data1
and data2
. Suppose my arrays are like:
int num1 = 4;
int num2 = 6;
double data1[num1] = /* some values */
double data2[mum2] = /* some values */
Solution 1
I can either use a solution I find more elegant but I'm unsure if it's good practice and will behave properly. The solution relies on a static variable intended to make the array persistent. Somehow that feels like it could blow up in my face some way.
// SOLUTION 1
double* combine_data(
const int num1, const double* const data1,
const int num2, const double* const data2
) {
int i;
int num = num1 + num2;
double *combi; // static because the data stored the should persist
combi = (double*)malloc( num*sizeof(*combi) );
/* some code */
for(i=0; i<num1; ++i) combi[i] = data[i];
for(i=num1; i<num; ++i) combi[i] = data[i];
return combi;
}
开发者_开发问答double *combi = combine_data(num1, data1, num2, data2);
/* some code */
free(combi); // problem with free of a static variable in combine_data() ???
Solution 2
Or I could use the approach I'm more used to, that uses pointers for the same functionality:
// SOLUTION 2
void combine_data(
const int num1, const double* const data1,
const int num2, const double* const data2
double* combi
) {
/* some code */
for(i=0; i<num1; ++i) combi[i] = data[i];
for(i=num1; i<num; ++i) combi[i] = data[i];
}
int num = num1 + num2;
double *combi = (double*)malloc( num*sizeof(combi) );
combine_data(num1, data1, num2, data2, combi);
/* some code */
free(combi);
Solution 2 has the problem that nothing prevents the user from this: combine_data(num1, data1, num2, data2, data1)
, which would screw up data1
. Solution 2 hides the allocation, and is easier to use, which I find more elegant, but I don't know how it will behave especially when freeing the memory. Which solution is the best and why?
Also btw. is there a difference between the two?:
const int* const name
const int const *name
Edit: One really is a syntax error i've seen in faulty code and wondered. Also discarded the static
.
Why would you need to make combi
static in solution 1? The pointer does not have to persist, only what is pointed to by it. The pointer is then returned by value, so no memory leak occurs.
Which solution you choose depends solely on your assumption as to the style of the whole program. You have to decide whether the function should allocate and return a pointer to allocated memory, or accept a pointer to already allocated memory.
Both solutions are correct, and in my opinion equally good. In solution 2 you may also check for equality between input and output pointers and return an error code. You can even check for memory overlapping, not only pointer equality. But then again, it all depends on what responsibilities you assign to different parts of your program.
Your second solution is better. Static variables are going to kill you would you ever go multithreaded.
As of prventing the user from using your function wrong, you can assert that data1+num1
and data2+num2
don't overlap.
There is a difference between const int* const name
and const int* name
. The latter means you can't change the values pointed by name
but you can assign name
itself to another pointer, the former means you can't change the values nor the pointer.
is there a difference between const int* const name and const int const *name
Yes, the second is a syntax error.
As to which of the solutions is better... Well, I don't think that the problem that you're afraid in solution 2 isn't present in solution 1. You do return combi
in the first solution, so the user can save it and then pass it again to the same function which would screw things up as well. So, my vote goes for second solution. (by the way, you could check in the function that neither data1
nor data2
are equal to combi
)
The second solution has the advantage that you can pass it arrays of different storage classes. Global array, stack allocated (VLA) or heap allocated. This gives you more flexibility which might come handy if your function is used by different parts of a big project (imagine a library).
double combi[num1+num2];
combine_data(num1, data1, num2, data2, combi);
/* some code */
/*forget free(combi) it's not necessary anymore;
EDIT: Besides, the advantage of making the allocation in the caller instead of the callee can have also impact on the algorithmic complexity of the solution. If we imagine that your combine function is called in a loop. With the first solution you will have a lot of copies.
1st solution
data1, data2, data3, data4
comb1 = combine_data(len1, data1, len2, data2);
comb2 = combine_data(len3, data3, len4, data4);
comb3 = combine_data(len1+len2, comb1, len3+len4, comb2);
/* ... */
free(comb1);
free(comb2);
free(comb3);
2nd solution
data1, data2, data3, data4
comb = malloc(len1+len2+len3+len4);
combine_data(len1, data1, len2, data2, comb);
combine_data(len3, data3, len4, data2, comb+len1+len2); /* This case can of course only be used because we know what combine does */
/* ... */
free(comb);
The static
in the first solution serves no purpose, you can remove it and the function will function identical (except that it is threadsafe).
精彩评论