I'm trying to refactor a utility that is currently a stand-alone C program, such that I can make a reusable library. It includes a sorting step of an array, according to the corresponding value within a global array.
// Global lookup table
double *rating;
// Comparator using lookup
int comp_by_rating(const void *a, const void *b) {
int * x = (int *) a;
int * y = (int *) b;
if (rating[*x] > rating[*y])
return 1;
else if (rating[*x] < rating[*y])
return -1;
else
return 0;
}
int main() {
int* myarray;
// ...
// initialize values of local myarray and global rating
// ...
qsort(myarray, length_myarray, sizeof(int), comp_by_rating);
// ...
return 0;
}
Is there a way for me to avoid having the rating lookup table global? I'm traditionally a C++ person so my first thought was a functor, but I have to stay in C and so I guess I'm functor-less. I also can't replace int *myarray with an array of structs holding the rating for each item, since other code requires the array in its current form. Do I have any other options?
I also can't replace int *myarray with an array of structs holding the rating for each item, since other code requires the array in its current form.
You can make a temporary replacement for sorting, call qsort, and harvest the results back into the original array:
struct rated_int {
int n;
double r;
};
struct rated_int *tmp = malloc(length_myarray * sizeof(struct rated_int));
for (int i = 0 ; i != length_myarray ; i++) {
tmp[i].n = myarray[i];
tmp[i].r = ratings[myarray[i]];
}
qsort(tmp, length_myarray, sizeof(struct rated_int), comp_struct);
for (int i = 0 ; i != length_myarray ; i++) {
myarray[i] = tmp[i].n;
}
free(tmp);
This way the rest of the code would see myarray as an array of integers.
That's how you roll in C. If you are worried about thread-safety, consider making the variable thread-local, so multiple threads have different copies of it:
static _Thread_local double *rating;
This is not supported by old compilers though, instead you need some sort of portability kludge. If you don't like this either, you can't really get around writing your own sorting routine that allows an extra parameter.
gcc provides nested functions as an extension to solve this problem, but they have other problems, namely, they require an executable stack which reduces the resilience of your program against bugs.
No, the array rating does not have to be global: You can use static here:
int comp_by_rating(const void *a, const void *b) {
static double *rating = { .. init here .. };
Alternate way to initialize it if members are non-constant:
int comp_by_rating(const void *a, const void *b) {
static double *rating = NULL;
if (!rating) {
// Initialize rating here
}
}
Related
I have an array of structures as a function parameter and the size of the array is dynamic. My coworker said that I'll have to use a double pointer since the values contained in the array of struct will be overwritten.
The parameter that will become a double pointer is the following :
xPIDConfig_t **pxPIDConfig
Here is what the structure looks like for the xPIDConfig_t :
typedef struct
{
ePIDType_t ePIDType;
/* Common fields for the different types of PID */
float fLowerSaturationLimit;
float fUpperSaturationLimit;
float fOldInput;
float fIError;
uint32_t ulDeltaTime;
eBool_t bSaturationEnable;
eBool_t bAntiWindupEnable;
eBool_t bNegativeErrorEmptyIError;
union
{
/* Parallel PID fields */
struct
{
float fProportionalGain;
float fIntegralGain;
float fDerivativeGain;
}xParallelPID;
/* Non-interactive PID fields */
struct
{
float fControllerGain;
uint32_t ulIntegralTime;
uint32_t ulDerivativeTime;
}xNonInteractivePID;
}xUniqueFields;
}xPIDConfig_t;
The size of the array of pxPIDConfig will vary.
But I am not sure how to malloc that double pointer or even how to use the function containing the double pointer.
I was just wondering if anyone had a good example of code of how to use a function with a double pointer array of variating size? and how to properly change the values contained in the array itself inside a function?
Right now this is how I change the values within the function :
pxPIDConfig->ePIDType = ePIDType;
pxPIDConfig->fOldInput = 0;
pxPIDConfig->fIError = 0;
pxPIDConfig->ulDeltaTime = ulDeltaTime;
pxPIDConfig->bSaturationEnable = bIsSaturationEnable;
pxPIDConfig->bAntiWindupEnable = bIsAntiWindupEnable;
pxPIDConfig->bNegativeErrorEmptyIError = bNegativeErrorEmptyIError;
when the pointer is double do I have to use double '->'? This is very confusing for me.
Thank you all for the help
/***************** EDIT ************************************
My function is working right now, but I got told I need to use memory allocation since the size of my arrays varies according to the number of loops I want to implement.
Here are the parameters of my function :
eError_t eControlCascadeInit( uint8_t ucNumberOfLoops, ePIDType_t *pePIDType, xPIDConfig_t **pxPIDConfig, float *pfLowerLimit, float *pfUpperLimit, uint32_t *pulDeltaTime, \
eBool_t *pbIsSaturationEnable, eBool_t *pbIsAntiWindupEnable, eBool_t *pbNegativeErrorEmptyIError, \
float *pfPGain, float *pfIGain, float *pfDGain, float *pfCGain, uint32_t *pulITime, uint32_t *pulDTime )
They're all arrays of size ucNumberOfLoops. All of them are read-only arrays, except for the pxPIDConfig one that is write-only. The function initializes all the xPIDConfig_t present in the array with the parameters passed to the function through array.
array[ 0 ] contains the parameters for the first PID controller being initialized.
array[ 1 ] contains the parameters for the second PID controller being initialized and so on...
It's like that for all the parameters in the function.
Hope it makes my question more clear?
Here you have an example of how to use double-pointer, to change the pointer in the function:
void allocate(xPIDConfig_t **array, size_t size)
{
*array = malloc(sizeof(**array) * size);
/* some examples how to access the struct members vi double pointer -*
(*array) -> ulDeltaTime = 100;
(**array).ulDeltaTime = 100;
(*(array + 5)) -> ulDeltaTime = 100;
array[5] -> ulDeltaTime = 100;
(*array[5]).ulDeltaTime = 100;
}
int main(void)
{
xPIDConfig_t *array;
allocate(&array, 100);
printf("%s\n", array ? "success" : "failure");
free(array);
}
You would only need a double pointer if the function reallocates the array to a different size. If the size isn't changing, you can just pass a pointer to (usually the first) element of the array, along with any size or index required by the function. For example:
extern void frobPidConfig(xPIDConfig_t *);
// 'frob' the xPIDConfig_t array elements from index a to b
void frobSomePidConfigs(xPIDConfig_t *pidconfigs, unsigned int a, unsigned int b)
{
unsigned int i;
for (i = a; i <= b; i++)
{
frobPidConfig(&pidConfigs[i]);
// Example of member access:
pidConfigs[i].ulDeltaTime = 42;
}
}
Example of calling code:
xPIDConfig_t *pidConfigs;
unsigned int n = 10; // or whatever...
pidConfigs = calloc(sizeof *pidConfigs, n);
if (!pidConfigs)
{
// Allocation error
exit(1);
}
/* ... */
frobSomePidConfigs(pidConfigs, 2, 5);
On the other hand, if the function needs to reallocate the array and initialize any new elements, it could be done using a double pointer like this:
extern void initPidConfig(xPIDConfig_t *);
void reallocPidConfigs(xPIDConfig_t **pidConfigs, unsigned int oldSize, unsigned int newSize)
{
unsigned int i;
// Reallocate to new size
xPIDConfig_t *realloced = realloc(*pidConfigs, sizeof **pidConfigs * newSize);
if (newSize && !realloced)
{
// allocation error
exit(EXIT_FAILURE);
}
*pidConfigs = realloced;
// Initialize any additional elements
for (i = oldSize; i < newSize; i++)
{
initPidConfig(*pidConfigs + i); // or: initPidConfig(&(*pidConfigs)[i]);
// Examples of member access:
(*pidConfigs)[i].bSaturationEnable = true;
(*pidConfigs + i)->bAntiWindupEnable = true;
}
}
Example of calling code:
xPIDConfig_t *pidConfigs = NULL;
// Note: realloc of the NULL pointer in *pidConfigs is OK.
reallocPidConfigs(&pidConfigs, 0, 10);
frobSomePidConfigs(pidConfigs, 2, 5);
Limited to addressing assumptions and questions regarding your title question:
"How to use double pointers (pointer to pointer) for an array of structures properly in standard C"
First, just because the function argument might have a double pointer (i.e. xPIDConfig_t **pxPIDConfig) does not mean that the variable need to be allocated memory with a double pointer, i.e. if the function eg is called like this: funcChangeParam(&pxPIDConfig); this often means that the object being passed needs to be changed in some way, requiring that the address of be passed, not the object itself. Also, if the object itself is a pointer, (such as a pointer to several instances of a struct object.) then the function used to pass the object for modification will be prototyped with arguments such as void funcChangeParam(xPIDConfig_t **pxPIDConfig); (Note the double pointer here.)
So with this function prototype Making the allocation of memory look like this:
void funcChangeParam(xPIDConfig_t **pxPIDConfig);
//allocate memory for multiple instances of struct
xPIDConfig_t *pxPIDConfig = malloc(countOfInstances * sizeof(*pxPIDConfig);
if(pxPIDConfig)
{
//use pxPIDConfig
funcChangeParam(&pxPIDConfig);pass pointer to multiple instances of struct
And references to the object members inside the calling function could use the following notation. Eg:
//in a loop or other construct where i is defined from 0 to countOfInstances - 1
(*pxPIDConfig)[i].ePIDType = ePIDType;//modification of assignment per your example
//etc.
//The following is a trivial example for illustration purposes.
//Code here uses a simplified struct, function
//prototype, and simple calling example, the concept
//of which easily translates to what you are
//asking about.
typedef struct {
int num;
}test_s;
void change(test_s **new);
int main(){
test_s *test = malloc(10*sizeof *test);
change(&test);
return 0;
}
void change(test_s **new)
{
for(int i=0;i<10;i++)
{
(*new)[i].num = (i+1)*3; //init all instances to some value
}
}
I searched for the implementation of suffix array in C, but all the programs I saw were in C++ which used sort. I am not sure how can I use the built-in function of C, qsort() in place of sort() function of C.
Can we implement suffix arrays without using qsort()?
or
how to use qsort() to implement suffix arrays in C?
here is the code that I got from geeksforgeeks.com:
int cmp(struct suffix a, struct suffix b)
{
return strcmp(a.suff, b.suff) < 0? 1 : 0;
}
int *buildSuffixArray(char *txt, int n)
{
// A structure to store suffixes and their indexes
struct suffix suffixes[n];
// Store suffixes and their indexes in an array of structures.
// The structure is needed to sort the suffixes alphabatically
// and maintain their old indexes while sorting
for (int i = 0; i < n; i++)
{
suffixes[i].index = i;
suffixes[i].suff = (txt+i);
}
// Sort the suffixes using the comparison function
// defined above.
sort(suffixes, suffixes+n, cmp);
// Store indexes of all sorted suffixes in the suffix array
int *suffixArr = new int[n];
for (int i = 0; i < n; i++)
suffixArr[i] = suffixes[i].index;
// Return the suffix array
return suffixArr;
}
the cmp function is comparing structure data type while I am getting an error when using qsort(), which says that only void input is allowed.
The declaration of the qsort function is as follows:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
You'll notice that the comparison function it accepts must be defined to take a const void * for each of its two parameters, but you're instead passing in a struct suffix for each one.
You need to change your comparison function to use the parameter types that qsort expects. Then you can convert those parameters inside of the function to the proper pointer type and use those.
int cmp(const void *p1, const void *p2)
{
const struct suffix *a = p1;
const struct suffix *b = p2;
return strcmp(a->suff, b->suff) < 0? 1 : 0;
}
A function like that:
int * getRandom( ) {
static int r[10];
int i;
/* set the seed */
srand( (unsigned)time( NULL ) );
for ( i = 0; i < 10; ++i) {
r[i] = rand();
printf( "r[%d] = %d\n", i, r[i]);
}
return r;
}
Is this one possible to be used in Vivado HLS? If possible, how can I initialize an array of unknown size because I cannot use static and malloc anymore?
Converting comments into an answer.
You cannot, in standard C, return an array from a function — you can return a pointer OK (so the code shown is permissible, though it clearly has re-entrancy and threading issues). If you can't use static or malloc() et al, then you need to pass the array to the function for it to fill in instead of returning the array. Then it is the caller's responsibility to allocate the space.
See also srand() — why call it only once.
So you mean I can set a global array as function arguments and give value to each element so I can get the array without using static and malloc?
Yes, or a local array, or an any-other-type of array you care to think of. I think the appropriate implementation might be:
void getRandom(int n_vals, int *i_vals)
{
for (int i = 0; i < n_vals; i++)
i_vals[i] = rand();
}
but the possible variations are legion. You can reinstate the printing if you really want it; you can even call srand() if you really want to (but you should only call that once). You can then use it like:
void somefunc(void)
{
int data[20];
getRandom(15, data);
…use data…;
}
or
static int data[20];
void somefunc(void)
{
getRandom(18, data);
…use data…;
}
or other variants (such as not using static in front of the file-scope definition of data — converting it into a global variable). (Yes, you'd probably use 10 as in the question, or 20 as the amount of space in the array — but 15 and 18 are also OK values in their context.)
I need to pass the address of a pointer to a structure to a function, which inturn will dynamically allocate the memory for an array of structures and fill in the values.
Now from my calling method, once i return from the func1, i should be able to iterate through the array of structure and display the value of the structure variables.
Can someone explain how to pass the address of the pointer to the structure, also iterating through the array of structures created dynamically ?
my sample code looks like this:
struct test {
int a;
int b;
};
void func1(int *n,struct test **testobj)
{
n=5;
*testobj = (struct test*) malloc(n*sizeof(struct test));
for(i=0;i<n;i++)
{
(*testobj)[i].a=1;
(*testobj)[i].b=2;
}
}
int main()
{
struct test testobj;int n;
func1(&n,&testobj);
for(i=0;i<n;i++)
{
printf("%d %d",(*testobj)[i].a,*testobj)[i].b);
}
free(testobj);
}
In main() define a pointer to a test structure:
struct test *testPtr;
To take the address of that pointer use the & address-of operator:
&testPtr;
This returns the address of the pointer and has type struct test **
You can then pass this into your function func1, which does the correct allocation (although casting malloc() is generally considered bad practice - Do I cast the result of malloc?). Other than that func1() looks good... the line...
*testobj = malloc(n*sizeof(struct test));
... is correct. *testobj dereferences your double pointer that you got by doing &testPtr, and stores the address of the new memory in your pointer. You are also correct when you dereference your double-pointer using (*testobj)[i] because [] has higher precedence than * you needed to (as you've correctly done) surround the dereference with brackets to make sure that happens before you take the index.
Thus, when func1() returns the pointer testPtr should now point to the array of n test structures you allocated and can be accessed using testPtr[i].a etc.
EDIT: Your for loop should become
for(i=0;i<n;i++)
printf("%d %d", testobj[i].a, testobj[i].b);
Your original for loop should have given you compilation errors? In the original code testobj is not a pointer, therefore dereferencing it should not be possible.
So the summary answer is in main() declare testobj as a pointer and then access the array elements as testobj[n] :)
EDIT: As eric has pointed out, remove n=5; from func1(). I think you meant *n=5 perhaps as some kind of debugging step... You probably mean to use n as the input to the function to say how many objects you want in your structure array. Either initialise n or perhaps re-define func1() to be
void func1(int n,struct test **testobj) // n is no longer a poitner, just a number
create your array of pointers to structures in declaration step itself and simply pass it to the function
struct test *testobj[10];
func1(&n,testobj);
This passes the whole array of pointers to the function
It isn't entirely clear which version you're asking for, but one of these should cover it:
/* allocate some number of tests.
*
* out_n: out parameter with array count
* returns: an array of tests
*/
struct test* allocate_some_tests(int *out_n) {
int n = 5; /* hardcoded, random or otherwise unknown to caller */
*out_n = n
struct test *t = malloc(n * sizeof(*t));
while (n--) {
t[n].a = 1;
t[n].b = 2;
}
return t;
}
/* allocate a specific number of tests.
*
* n: in parameter with desired array count
* returns: an array of tests
*/
struct test* allocate_n_tests(int n) {
struct test *t = malloc(n * sizeof(*t));
while (n--) {
t[n].a = 1;
t[n].b = 2;
}
return t;
}
Note that you can just return the allocated array, you don't need a pointer-to-pointer here.
As for calling them, and iterating over the result:
void print_tests(struct test *t, int n) {
for (; n--; t++)
printf("{%d, %d}\n", t->a, t->b);
}
int main()
{
int count1; /* I don't know how many yet */
struct test *array1 = allocate_some_tests(&count1);
print_tests(array1, count1);
int count2 = 3; /* I choose the number */
struct test *array2 = allocate_n_tests(count2);
print_tests(array2, count2);
}
Your code appears pretty much ok to me.
only edit that should make it fine is--
in place of
struct test testobj;
put the following code
struct test *testobj;
and keep the remaining as it is..!
here's the working version of what's required, here the memory is allocated in the called function just as required
#include <stdlib.h>
#include <stdio.h>
struct tests {
int a;
int b;
};
void func1(int *n,struct tests **testobj)
{
int i;
*n=5;
*testobj = (struct tests*) malloc((*n)*sizeof(struct tests));
for(i=0;i<(*n);i++)
{
(*testobj)[i].a=1;
(*testobj)[i].b=2;
}
}
int main()
{
int i;
struct tests *testobj;int n;
func1(&n,&testobj);
for(i=0;i<(n);i++)
{
printf("%d %d",(testobj)[i].a,testobj[i].b);
}
free(testobj);
}
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
returning multiple values from a function
I have a function which has to return two values
return(&ptr->keys[pos].value)
return Duplicate;
Here &ptr->keys[pos].value will give the address and Duplicate is a enum value set to 2... How to return these two values to another function, insert_front which is a linked list this &ptr->keys[pos].value is used as the first address for linked list.
What should be the prototype of the calling function I should write?
You can't return two values. However, you can return a single value that is a struct that contains two values.
You can return only one thing from a function. Either you make a struct which contains all the things you want to return, or you pass some function parameters by reference.
Robert's code is correct. However, you /can/ also use a struct without malloc, like so:
struct retstruct {
int a;
int b;
};
struct retstruct myfunc(void) {
struct retstruct r;
r.a = 1;
r.b = 2;
return r;
}
int main()
{
struct retstruct r;
r = myfunc();
printf("a=%d b=%d\n", r.a, r.b);
}
This is typically shunned because it's generally a bit more costly (performance-wise) to be passing around structs like this, but if you only need a couple values like this, it can be sufficient.
To return two values, you'll have to define some sort of struct to hold both values, and return an instance of that struct. Alternatively, you can pass an address or two to the function, and have it write the value(s) there.
No, you can not have two returns in a function, the first return will exit the function you will need to create an object. Note: I have not coded in C in a long time, so the syntax here is probably off.
public class link{
private int& ptr;
private int Duplicate;
public constructor link() {}
public setPtr(int& ptr) {
this->&ptr = ptr;
}
//set duplicate function
//get ptr function
//get duplicate function
}
and in the function you snippet you posted before create a link object set the values desired, and then return(link object);
In C/C++, a function cannot return two values. However, most often, this limitation actually makes sense: in any complex function, you want to update some data (a bunch of variables, an array, etc.), and return the status of the function, i.e., whether it was successful or not. As a result, a good practice is to return the status of the function, and use references (in C++) or pointers (in C) to modify your arguments, just like in this example in C:
int swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
return 0;
}
Of course, this function is too simple to fail (sort of), but you get the idea :P
And then, if you really want your function to return 2 values, then you can use all the tricks proposed by the other answerers.
Like this:
typedef ret {
int val1;
int *val2;
} ret_t ;
// make sure to remember to free the struct when you're done with it
ret_t *myFunc( void ) {
ret_t *r = malloc( sizeof(ret_t) );
r->val1 = 1;
r->val2 = &r.val1;
return r;
}
// You can also return a copy of the struct on the stack
ret_t myFunc( void ) {
ret_t r;
r.val1 = 1;
r.val2 = &r.val1;
return r;
}