SDDC Cast of literal value to 'generic' pointer - c

I am writing an at command for a radio module, I am trying to use the following function, however I cannot seem to pass anything for the 2nd argument that the compiler (SDDC) likes.
Function:
radio_receive_packet(uint8_t *length, __xdata uint8_t * __pdata buf)
My code:
static void
at_find(void)
{
__xdata uint8_t mbuf[MAX_PACKET_LENGTH];
// Cycle netID's 1-1000
int i;
for(i=1; i<=1000; i++)
{
param_set(3, i);
param_save();
if (radio_receive_packet(MAX_PACKET_LENGTH, mbuf))
{
printf("Traffic found at %d\n", i);
}
}
at_ok();
}
running this code produces the following error:
radio/at.c:403: error 88: cast of LITERAL value to 'generic'
pointer from type 'const-unsigned-char literal' to type
'unsigned-char generic* fixed'
I've been slamming my head against a wall, I've used C before but not with SDDC or the xdata and pdata types. Also I have never been real strong with pointers and such. Any advice would be appreciated, Another section of the radio code uses this function exactly how I am, only the buffer is declared globally.

As per the function signature
radio_receive_packet(uint8_t *length, __xdata uint8_t * __pdata buf)
the first argument should be a pointer. In your case,
if (radio_receive_packet(MAX_PACKET_LENGTH, mbuf))
it pretty much looks like a MACRO value, maybe of type int or const-unsigned-char literal whatever, but not certainly a uint8_t *.
Hint: __xdata uint8_t mbuf[MAX_PACKET_LENGTH]; Notice the array size.

I'd like to extend #SouravGhosh's answer with a solution: You should define a variable holding the buffer length at the beginning of your at_find() function:
uint8_t buffer_length = MAX_PACKET_LENGTH;
Then you pass a pointer to that variable as first parameter to the radio_receive_packet() function:
if (radio_receive_packet(&buffer_length, mbuf))
{
[...]
}
So your problem seems to be with the first parameter and not the second parameter.

Related

Point to functions with different arguments using the same pointer

I am trying to build a parser to a given input, there are 8 possible commands. So I figured that instead of using the ugly technique of a case switch block like that:
switch(command)
case cmd1:
.... /*call a function that do cmd1*/
case cmd2
..../*call a function that do cmd2*/
I will define in a header an array of structs, each one contains the name of the function, and a pointer to a function:
typedef struct command_info
{
char *name;
void (*func)(int)
};
command_info command_table[] = {{"func1", &func1}, {"func2", &func2} }
So that I can switch to the more elegant:
int i;
for(i = 0; i < COMMAND_TABLE_LENGTH; i++)
if(!strcmp(command_table[i].name, command))
command_table[i].func(2);
My only problem is, that the functions have different parameters (all return void). This is not a problem for me since I can check if the function is func1 or func2 search for one int argument for example, and if it is func3 or func4 search for two (still more compact than case switch). But the function pointer only points to a function with a certain type and amount of arguments. How can I make a universal pointer that can point to any function?
But the function pointer only points to a function with a certain type and amount of arguments.
How can I make a universal pointer that can point to any function?
In OP's limited case, use void (*func)().
Any function pointer can be converted with a type cast to another function pointer and retain an equivalent function address. #Jonathan Leffler
int (*foo)(int) = (int (*)(int)) sqrt;
double (*sq)(double) = (double (*)(double)) foo;
printf("%f\n", sq(2)); // prints 1.414214
A function pointer need not provide a function parameter signature.
// No parameter info
// vv
int (*foo)() = (int (*)()) sqrt;
OP has "functions have different parameters (all return void)", so in OP's case code could use a limited universal function pointer of void (*func)() and lose parameter checking.
typedef struct {
char *name; // suggest const char *name
void (*func)(); // no parameter info nor checking
} command_info;
char buf[100];
// void setbuf(FILE * restrict stream, char * restrict buf);
command_info fred = { "my_setbuf", setbuf };
// Both compile, 2nd is UB.
fred.func(stdin, buf); // No parameter checking.
fred.func(0); // No parameter checking.
Code also incurs a subtle issue when calling .funf(): the parameters ranking lower than int/unsigned are promoted as well as float parameters before passed to the function. Best to make certain the parameters are not char, float, short, _Bool etc. to avoid compatible signature issues.
void * is a universal object pointer. It may be insufficient to encode a function pointer. So it is not a portable candidate. It is not uncommon for the size of a function pointer to be wider than sizeof(void*).

C: Passing array to pointer function

I'm not sure if the question has asked before, but I couldn't find any similar topics.
I'm struggeling with the following piece of code. The idea is to extend r any time later on without writing lots of if-else statements. The functions (func1, func2...) either take zero or one arguments.
void func1() {
puts("func1");
}
void func2(char *arg){
puts("func2");
printf("with arg %s\n", arg);
}
struct fcall {
char name[16];
void (*pfunc)();
};
int main() {
const struct fcall r[] = {
{"F1", func1},
{"F2", func2}
};
char param[] = "someval";
size_t nfunc = RSIZE(r); /* array size */
for(;nfunc-->0;) {
r[nfunc].pfunc(param);
}
return 0;
}
The code above assumes that all functions take the string argument, which is not the case. The prototype for the pointer function is declared without any datatype to prevent the incompatible pointer type warning.
Passing arguments to functions that do not take any parameters usually results in too few arguments. But in this case the compiler doesn't 'see' this ahead, which also let me to believe that no optimization is done to exclude these unused addresses from being pushed onto the stack. (I haven't looked at the actual assemble code).
It feels wrong someway and that's usually a recipe for buffer overflows or undefined behaviour. Would it be better to call functions without parameters separately? If so, how much damage could this do?
The way to do it is typedef a function with 1 argument, so the compiler could verify if you pass the correct number of arguments and that you do not pass something absolutely incompatible (e.g. a struct by value). And when you initialize your array, use this typedef to cast function types.
void func1(void) { ... }
void func2(char *arg) { ... }
void func3(int arg) { ... }
typedef uintptr_t param_t;
typedef void (*func_t)(param_t);
struct fcall {
char name[16];
func_t pfunc;
};
const struct fcall r[] = {
{"F1", (func_t) func1},
{"F2", (func_t) func2}
{"F3", (func_t) func3}
};
...
r[0].pfunc((param_t) "foo");
r[1].pfunc((param_t) "bar");
r[2].pfunc((param_t) 1000);
Here param_t is defined as uintpr_t. This is an integer type big enough to store a pointer value. For details see here: What is uintptr_t data type.
The caveat is that the calling conventions for param_t should be compatible with the function arguments you use. This is normally true for all integer and pointer types. The following sample is going to work, all the type conversions are compatible with each other in terms of calling conventions:
// No problem here.
void ptr_func(struct my_struct *ptr) {
...
}
...
struct my_struct struct_x;
((func_t) &ptr_func)((param_t) &struct_x);
But if you are going to pass a float or double argument, then it might not work as expected.
// There might be a problem here. Depending on the calling
// conventions the value might contain a complete garbage,
// as it might be taken from a floating point register that
// was not set on the call site.
void float_func(float value) {
...
}
...
float x = 1.0;
((func_t) &float_func)((param_t) x);
In this case you might need to define a function like this:
// Problem fixed, but only partially. Instead of garbage
// there might be rounding error after the conversions.
void float_func(param_t param) {
float value = (float) param;
...
}
...
float x = 1.234;
((func_t) &float_func)((param_t) x);
The float is first being converted to an integer type and then back. As a result the value might be rounded. An obvious solution would be to take an address of x and pass it to modified a function float_func2(float *value_ptr). The function would dereference its pointer argument and get the actual float value.
But, of course, being hardcore C-programmers we do not want to be obvious, so we are going to resort to some ugly trickery.
// Problem fixed the true C-programmer way.
void float_func(param_t param) {
float value = *((float *) &param);
...
}
...
float x = 1.234;
((func_t) &float_func)(*((param_t *) &x));
The difference of this sample compared to passing a pointer to float, is that on the architecture (like x86-64) where parameters are passed on registers rather than on the stack, a smart enough compiler can make float_func do its job using registers only, without the need to load the parameter from the memory.
One option is for all the functions accept a char * argument, and your calling code to always pass one. The functions that don't need an argument need not use the argument they receive.
To be clean (and avoid undefined behaviour), if you must have some functions that accept no argument and some functions that accept an argument, use two lists and register/call each type of function separately.
If the behaviour is undefined there's no telling how much damage could be caused.
It might blow up the planet. Or it might not.
So just don't do it, OK?

Calling Inline Function in Macro Preprocessor of a C Program

I am confused by the following macro pre-processor definition:
#define HOOK_SYSCALL(NAME) original_##NAME = get_sys_call_table_addr()[__NR_##NAME];
The code for the function named get_sys_call_table_addr() is as follows:
ssize_t *sys_call_table = (ssize_t *)NULL;
void** get_sys_call_table_addr(void)
{
void *swi_addr=(long *)0xffff0008;
unsigned long offset=0;
unsigned long *vector_swi_addr=0;
offset=((*(long *)swi_addr)&0xfff)+8;
vector_swi_addr=*(unsigned long *)(swi_addr+offset);
while(vector_swi_addr++)
{
if(((*(unsigned long *)vector_swi_addr)& 0xfffff000)==0xe28f8000)
{
offset=((*(unsigned long *)vector_swi_addr)& 0xfff)+8;
sys_call_table=(void *)vector_swi_addr+offset;
break;
}
}
return (void **) sys_call_table;
}
I'd like to ask whether this specific line:
get_sys_call_table_addr()[__NR_##NAME];
is calling the inline function as an array? Like what we'd do to a normal kind of array, e.g. array[3];
Thanks!!
## is used to concatenate preprocessor tokens. Suppose the NAME is exit. Then get_sys_call_table_addr()[__NR_##NAME] will be
get_sys_call_table_addr()[__NR_exit]. This means that get_sys_call_table_addr() is called and the evaluated result will be a pointer.
Remember that arr[x] is *(arr + x). Let's say that __NR_exit is a constant with a value 1. Then, the resultant pointer returned by the function is moved by 1 and then dereferenced. This will now be assigned to the variable original_exit.
the token ## is used to concatenate two tokens into one. For example in the above example __NR_##NAME becomes __NR_NAME.
The function get_sys_call_table_addr() returns a table sys_call_table, which is a double pointer. This table shall be used as a array variable and points to address pointed by [__NR_NAME].
In otherwords, get_sys_call_table_addr()[__NR_##NAME] becomes sys_call_table[__NR_NAME];

generic programming in C with void pointer

Even though it is possible to write generic code in C using void pointer(generic pointer), I find that it is quite difficult to debug the code since void pointer can take any pointer type without warning from compiler.
(e.g function foo() take void pointer which is supposed to be pointer to struct, but compiler won't complain if char array is passed.)
What kind of approach/strategy do you all use when using void pointer in C?
The solution is not to use void* unless you really, really have to. The places where a void pointer is actually required are very small: parameters to thread functions, and a handful of others places where you need to pass implementation-specific data through a generic function. In every case, the code that accepts the void* parameter should only accept one data type passed via the void pointer, and the type should be documented in comments and slavishly obeyed by all callers.
This might help:
comp.lang.c FAQ list ยท Question 4.9
Q: Suppose I want to write a function that takes a generic pointer as an argument and I want to simulate passing it by reference. Can I give the formal parameter type void **, and do something like this?
void f(void **);
double *dp;
f((void **)&dp);
A: Not portably. Code like this may work and is sometimes recommended, but it relies on all pointer types having the same internal representation (which is common, but not universal; see question 5.17).
There is no generic pointer-to-pointer type in C. void * acts as a generic pointer only because conversions (if necessary) are applied automatically when other pointer types are assigned to and from void * 's; these conversions cannot be performed if an attempt is made to indirect upon a void ** value which points at a pointer type other than void *. When you make use of a void ** pointer value (for instance, when you use the * operator to access the void * value to which the void ** points), the compiler has no way of knowing whether that void * value was once converted from some other pointer type. It must assume that it is nothing more than a void *; it cannot perform any implicit conversions.
In other words, any void ** value you play with must be the address of an actual void * value somewhere; casts like (void **)&dp, though they may shut the compiler up, are nonportable (and may not even do what you want; see also question 13.9). If the pointer that the void ** points to is not a void *, and if it has a different size or representation than a void *, then the compiler isn't going to be able to access it correctly.
To make the code fragment above work, you'd have to use an intermediate void * variable:
double *dp;
void *vp = dp;
f(&vp);
dp = vp;
The assignments to and from vp give the compiler the opportunity to perform any conversions, if necessary.
Again, the discussion so far assumes that different pointer types might have different sizes or representations, which is rare today, but not unheard of. To appreciate the problem with void ** more clearly, compare the situation to an analogous one involving, say, types int and double, which probably have different sizes and certainly have different representations. If we have a function
void incme(double *p)
{
*p += 1;
}
then we can do something like
int i = 1;
double d = i;
incme(&d);
i = d;
and i will be incremented by 1. (This is analogous to the correct void ** code involving the auxiliary vp.) If, on the other hand, we were to attempt something like
int i = 1;
incme((double *)&i); /* WRONG */
(this code is analogous to the fragment in the question), it would be highly unlikely to work.
Arya's solution can be changed a little to support a variable size:
#include <stdio.h>
#include <string.h>
void swap(void *vp1,void *vp2,int size)
{
char buf[size];
memcpy(buf,vp1,size);
memcpy(vp1,vp2,size);
memcpy(vp2,buf,size); //memcpy ->inbuilt function in std-c
}
int main()
{
int array1[] = {1, 2, 3};
int array2[] = {10, 20, 30};
swap(array1, array2, 3 * sizeof(int));
int i;
printf("array1: ");
for (i = 0; i < 3; i++)
printf(" %d", array1[i]);
printf("\n");
printf("array2: ");
for (i = 0; i < 3; i++)
printf(" %d", array2[i]);
printf("\n");
return 0;
}
The approach/strategy is to minimize use of void* pointers. They are needed in specific cases. If you really need to pass void* you should pass size of pointer's target also.
This generic swap function will help you a lot in understanding generic void *
#include<stdio.h>
void swap(void *vp1,void *vp2,int size)
{
char buf[100];
memcpy(buf,vp1,size);
memcpy(vp1,vp2,size);
memcpy(vp2,buf,size); //memcpy ->inbuilt function in std-c
}
int main()
{
int a=2,b=3;
float d=5,e=7;
swap(&a,&b,sizeof(int));
swap(&d,&e,sizeof(float));
printf("%d %d %.0f %.0f\n",a,b,d,e);
return 0;
}
We all know that the C typesystem is basically crap, but try to not do that... You still have some options to deal with generic types: unions and opaque pointers.
Anyway, if a generic function is taking a void pointer as a parameter, it shouldn't try to dereference it!.

Solution for "dereferencing `void *' pointer" warning in struct in C?

I was trying to create a pseudo super struct to print array of structs. My basic
structures are as follows.
/* Type 10 Count */
typedef struct _T10CNT
{
int _cnt[20];
} T10CNT;
...
/* Type 20 Count */
typedef struct _T20CNT
{
long _cnt[20];
} T20CNT;
...
I created the below struct to print the array of above mentioned structures. I got dereferencing void pointer error while compiling the below code snippet.
typedef struct _CMNCNT
{
long _cnt[3];
} CMNCNT;
static int printCommonStatistics(void *cmncntin, int cmncnt_nelem, int cmncnt_elmsize)
{
int ii;
for(ii=0; ii<cmncnt_nelem; ii++)
{
CMNCNT *cmncnt = (CMNCNT *)&cmncntin[ii*cmncnt_elmsize];
fprintf(stout,"STATISTICS_INP: %d\n",cmncnt->_cnt[0]);
fprintf(stout,"STATISTICS_OUT: %d\n",cmncnt->_cnt[1]);
fprintf(stout,"STATISTICS_ERR: %d\n",cmncnt->_cnt[2]);
}
return SUCCESS;
}
T10CNT struct_array[10];
...
printCommonStatistics(struct_array, NELEM(struct_array), sizeof(struct_array[0]);
...
My intention is to have a common function to print all the arrays. Please let me know the correct way of using it.
Appreciate the help in advance.
Edit: The parameter name is changed to cmncntin from cmncnt. Sorry it was typo error.
Thanks,
Mathew Liju
I think your design is going to fail, but I am also unconvinced that the other answers I see fully deal with the deeper reasons why.
It appears that you are trying to use C to deal with generic types, something that always gets to be hairy. You can do it, if you are careful, but it isn't easy, and in this case, I doubt if it would be worthwhile.
Deeper Reason: Let's assume we get past the mere syntactic (or barely more than syntactic) issues. Your code shows that T10CNT contains 20 int and T20CNT contains 20 long. On modern 64-bit machines - other than under Win64 - sizeof(long) != sizeof(int). Therefore, the code inside your printing function should be distinguishing between dereferencing int arrays and long arrays. In C++, there's a rule that you should not try to treat arrays polymorphically, and this sort of thing is why. The CMNCNT type contains 3 long values; different from both the T10CNT and T20CNT structures in number, though the base type of the array matches T20CNT.
Style Recommendation: I strongly recommend avoiding leading underscores on names. In general, names beginning with underscore are reserved for the implementation to use, and to use as macros. Macros have no respect for scope; if the implementation defines a macro _cnt it would wreck your code. There are nuances to what names are reserved; I'm not about to go into those nuances. It is much simpler to think 'names starting with underscore are reserved', and it will steer you clear of trouble.
Style Suggestion: Your print function returns success unconditionally. That is not sensible; your function should return nothing, so that the caller does not have to test for success or failure (since it can never fail). A careful coder who observes that the function returns a status will always test the return status, and have error handling code. That code will never be executed, so it is dead, but it is hard for anyone (or the compiler) to determine that.
Surface Fix: Temporarily, we can assume that you can treat int and long as synonyms; but you must get out of the habit of thinking that they are synonyms, though. The void * argument is the correct way to say "this function takes a pointer of indeterminate type". However, inside the function, you need to convert from a void * to a specific type before you do indexing.
typedef struct _CMNCNT
{
long count[3];
} CMNCNT;
static void printCommonStatistics(const void *data, size_t nelem, size_t elemsize)
{
int i;
for (i = 0; i < nelem; i++)
{
const CMNCNT *cmncnt = (const CMNCNT *)((const char *)data + (i * elemsize));
fprintf(stdout,"STATISTICS_INP: %ld\n", cmncnt->count[0]);
fprintf(stdout,"STATISTICS_OUT: %ld\n", cmncnt->count[1]);
fprintf(stdout,"STATISTICS_ERR: %ld\n", cmncnt->count[2]);
}
}
(I like the idea of a file stream called stout too. Suggestion: use cut'n'paste on real source code--it is safer! I'm generally use "sed 's/^/ /' file.c" to prepare code for cut'n'paste into an SO answer.)
What does that cast line do? I'm glad you asked...
The first operation is to convert the const void * into a const char *; this allows you to do byte-size operations on the address. In the days before Standard C, char * was used in place of void * as the universal addressing mechanism.
The next operation adds the correct number of bytes to get to the start of the ith element of the array of objects of size elemsize.
The second cast then tells the compiler "trust me - I know what I'm doing" and "treat this address as the address of a CMNCNT structure".
From there, the code is easy enough. Note that since the CMNCNT structure contains long value, I used %ld to tell the truth to fprintf().
Since you aren't about to modify the data in this function, it is not a bad idea to use the const qualifier as I did.
Note that if you are going to be faithful to sizeof(long) != sizeof(int), then you need two separate blocks of code (I'd suggest separate functions) to deal with the 'array of int' and 'array of long' structure types.
The type of void is deliberately left incomplete. From this, it follows you cannot dereference void pointers, and neither you can take the sizeof of it. This means you cannot use the subscript operator using it like an array.
The moment you assign something to a void pointer, any type information of the original pointed to type is lost, so you can only dereference if you first cast it back to the original pointer type.
First and the most important, you pass T10CNT* to the function, but you try to typecast (and dereference) that to CMNCNT* in your function. This is not valid and undefined behavior.
You need a function printCommonStatistics for each type of array elements. So, have a
printCommonStatisticsInt, printCommonStatisticsLong, printCommonStatisticsChar which all differ by their first argument (one taking int*, the other taking long*, and so on). You might create them using macros, to avoid redundant code.
Passing the struct itself is not a good idea, since then you have to define a new function for each different size of the contained array within the struct (since they are all different types). So better pass the contained array directly (struct_array[0]._cnt, call the function for each index)
Change the function declaration to char * like so:
static int printCommonStatistics(char *cmncnt, int cmncnt_nelem, int cmncnt_elmsize)
the void type does not assume any particular size whereas a char will assume a byte size.
You can't do this:
cmncnt->_cnt[0]
if cmnct is a void pointer.
You have to specify the type. You may need to re-think your implementation.
The function
static int printCommonStatistics(void *cmncntin, int cmncnt_nelem, int cmncnt_elmsize)
{
char *cmncntinBytes;
int ii;
cmncntinBytes = (char *) cmncntin;
for(ii=0; ii<cmncnt_nelem; ii++)
{
CMNCNT *cmncnt = (CMNCNT *)(cmncntinBytes + ii*cmncnt_elmsize); /* Ptr Line */
fprintf(stdout,"STATISTICS_INP: %d\n",cmncnt->_cnt[0]);
fprintf(stdout,"STATISTICS_OUT: %d\n",cmncnt->_cnt[1]);
fprintf(stdout,"STATISTICS_ERR: %d\n",cmncnt->_cnt[2]);
}
return SUCCESS;
}
Works for me.
The issue is that on the line commented "Ptr Line" the code adds a pointer to an integer. Since our pointer is a char * we move forward in memory sizeof(char) * ii * cmncnt_elemsize, which is what we want since a char is one byte. Your code tried to do an equivalent thing moving forward sizeof(void) * ii * cmncnt_elemsize, but void doesn't have a size, so the compiler gave you the error.
I'd change T10CNT and T20CNT to both use int or long instead of one with each. You're depending on sizeof(int) == sizeof(long)
On this line:
CMNCNT *cmncnt = (CMNCNT *)&cmncnt[ii*cmncnt_elmsize];
You are trying to declare a new variable called cmncnt, but a variable with this name already exists as a parameter to the function. You might want to use a different variable name to solve this.
Also you may want to pass a pointer to a CMNCNT to the function instead of a void pointer, because then the compiler will do the pointer arithmetic for you and you don't have to cast it. I don't see the point of passing a void pointer when all you do with it is cast it to a CMNCNT. (Which is not a very descriptive name for a data type, by the way.)
Your expression
(CMNCNT *)&cmncntin[ii*cmncnt_elmsize]
tries to take the address of cmncntin[ii*cmncnt_elmsize] and then cast that pointer to type (CMNCNT *). It can't get the address of cmncntin[ii*cmncnt_elmsize] because cmncntin has type void*.
Study C's operator precedences and insert parentheses where necessary.
Point of Information: Internal Padding can really screw this up.
Consider struct { char c[6]; }; -- It has sizeof()=6. But if you had an array of these, each element might be padded out to an 8 byte alignment!
Certain assembly operations don't handle mis-aligned data gracefully. (For example, if an int spans two memory words.) (YES, I have been bitten by this before.)
.
Second: In the past, I've used variably sized arrays. (I was dumb back then...) It works if you are not changing type. (Or if you have a union of the types.)
E.g.:
struct T { int sizeOfArray; int data[1]; };
Allocated as
T * t = (T *) malloc( sizeof(T) + sizeof(int)*(NUMBER-1) );
t->sizeOfArray = NUMBER;
(Though padding/alignment can still screw you up.)
.
Third: Consider:
struct T {
int sizeOfArray;
enum FOO arrayType;
union U { short s; int i; long l; float f; double d; } data [1];
};
It solves problems with knowing how to print out the data.
.
Fourth: You could just pass in the int/long array to your function rather than the structure. E.g:
void printCommonStatistics( int * data, int count )
{
for( int i=0; i<count; i++ )
cout << "FOO: " << data[i] << endl;
}
Invoked via:
_T10CNT foo;
printCommonStatistics( foo._cnt, 20 );
Or:
int a[10], b[20], c[30];
printCommonStatistics( a, 10 );
printCommonStatistics( b, 20 );
printCommonStatistics( c, 30 );
This works much better than hiding data in structs. As you add members to one of your struct's, the layout may change between your struct's and no longer be consistent. (Meaning the address of _cnt relative to the start of the struct may change for _T10CNT and not for _T20CNT. Fun debugging times there. A single struct with a union'ed _cnt payload would avoid this.)
E.g.:
struct FOO {
union {
int bar [10];
long biff [20];
} u;
}
.
Fifth:
If you must use structs... C++, iostreams, and templating would be a lot cleaner to implement.
E.g.:
template<class TYPE> void printCommonStatistics( TYPE & mystruct, int count )
{
for( int i=0; i<count; i++ )
cout << "FOO: " << mystruct._cnt[i] << endl;
} /* Assumes all mystruct's have a "_cnt" member. */
But that's probably not what you are looking for...
C isn't my cup o'java, but I think your problem is that "void *cmncnt" should be CMNCNT *cmncnt.
Feel free to correct me now, C programmers, and tell me this is why java programmers can't have nice things.
This line is kind of tortured, don'tcha think?
CMNCNT *cmncnt = (CMNCNT *)&cmncntin[ii*cmncnt_elmsize];
How about something more like
CMNCNT *cmncnt = ((CMNCNT *)(cmncntin + (ii * cmncnt_elmsize));
Or better yet, if cmncnt_elmsize = sizeof(CMNCNT)
CMNCNT *cmncnt = ((CMNCNT *)cmncntin) + ii;
That should also get rid of the warning, since you are no longer dereferencing a void *.
BTW: I'm not real sure why you are doing it this way, but if cmncnt_elmsize is sometimes not sizeof(CMNCNT), and can in fact vary from call to call, I'd suggest rethinking this design. I suppose there could be a good reason for it, but it looks really shaky to me. I can almost guarantee there is a better way to design things.

Resources