Assuming I have the following code:
struct str1
{
int common1;
char common2;
char *common3;
long int aaaaaaaa;
}
struct str2
{
char bbbb;
char *common3;
int common1;
char common2;
}
struct str3
{
char ccccccccc[200];
int common1;
char common2;
int dddddddd;
int eeeeeeee;
char *common3;
}
void somefunc1(struct str1 var)
{
printf("%d %c %s", var.common1, var.common2, var.common3);
}
void somefunc2(struct str2 var)
{
printf("%d %c %s", var.common1, var.common2, var.common3);
}
void somefunc3(struct str3 var)
{
printf("%d %c %s", var.common1, var.common2, var.common3);
}
Can I somehow avoid code duplication and use a single generic function? Function calls are to be decided at runtime, therefore a macro is irrelevant. All the difference between the functions is the structs' names, not their members.
Since the position of the "common" structure members are not consistent between the structures, the answer is no. Because of this, there is really no actual commonality between the structure.
With these structure it is hard (if not impossible) to write a single function that will handle them all. But, if you change these structure to share those common elements from another structure then it will be possible.
struct base
{
int common1;
char common2;
char *common3;
};
struct str1
{
struct base b;
long int aaaaaaaa;
};
struct str2
{
struct base b;
char bbbb;
};
struct str3
{
struct base b;
char ccccccccc[200];
int dddddddd;
int eeeeeeee;
};
Note: variable of struct base structure should be the first member of each struct, otherwise this technique won't work.
Now declare a function that take pointer to struct base.
void somefunc(struct base* var)
{
printf("%d %c %s\n", var->common1, var->common2, var->common3);
}
Usages:
struct str1 s1 = { 1, 'a', "sfad"};
struct str2 s2 = { 2, 'b', "sdfazx"};
struct str3 s3 = { 3, 'c', "oiurotu"};
somefunc((struct base*) &s1);
somefunc((struct base*) &s2);
somefunc((struct base*) &s3);
Can I somehow avoid code duplication and use a single generic function?
No. That sounds analogous to a C++ template, which of course C doesn't have and has no analog for, unless you include the preprocessor. C11 has _Generic, but that yields a kind of function overloading: one function per type, with preprocessor support to call them by a single name.
Function calls are to be decided at runtime
In C and C++, a function call -- the path of control -- is determined at compile time. There is no runtime "decision".
All the difference between the functions is the structs' names, not their members.
Actually, a key difference is in each struct's layout. The names are at different locations. The C compiler converts names to locations. After compilation, there are no names and no types, nothing to indicate that a location was named common1 or was part of a struct. There is only a reference to a memory location. It's up to you to use the language correctly, to ensure that reference is to a location you intended.
therefore a macro is irrelevant.
The preprocessor lets you manipulate names before the compiler converts them to numbers. If you want to do anything in C "by name", a macro is the only game in town.
In C89, if two or more structures start with members of matching types in matching order (they share a Common Initial Sequence) and both are part of the same union, any part of the Common Initial Sequence may be inspected using the appropriate named members of any type sharing the CIS. Your example doesn't use matching types, so it doesn't qualify, but if it were to use matching types in matching order, it would. So far as I can tell, C89 compilers through the 1990s unanimously applied the same principle with pointers to structures (so if structure types S1 and S2 have a CIS, a pointer of either type could be used to access members of the CIS). While the Standard didn't explicitly specify such treatment, the easiest way by far for a compiler to ensure that the rule would be applied in all cases involving unions was to make it apply in all cases with pointers as well, and many people (likely including the authors of the Standard) expected that compilers would naturally do so whether explicitly required or not.
C99 requires that if code is going to use a pointer of one structure type to
access a member of the CIS of another, a complete definition of the union type must be visible to let the compiler know of the potential aliasing between the types. Unfortunately, although this rule has a clear and obvious purpose (allowing programmers to exploit the CIS rule while allowing compilers to assume that accesses to totally unrelated structures won't alias) some compiler writers will assume that no pointer of a structure type will be used to access any other, even when a complete union type declaration containing both types is visible, and even in cases where the structures are, in fact, members of the same union object.
If you want to exploit the Common Initial Sequence rule, it may be necessary to use the -fno-strict-aliasing flag when using compilers that have one (even when not exploiting the CIS, using the flag may provide protection against compiler bugs). Code which exploits aliasing should endeavor to make it obvious to the compiler (e.g. by ensuring that a suitable union type is visible) but unless or until compiler writers start paying attention to such things, -fno-strict-aliasing will be necessary to accommodate their failure to do so.
Looks like I was wrong about restricting usage of the preprocessor:
#include <stdio.h>
struct str1
{
int common1;
char common2;
char *common3;
long int aaaaaaaa;
};
struct str2
{
char bbbb;
char *common3;
int common1;
char common2;
};
struct str3
{
char ccccccccc[200];
int common1;
char common2;
int dddddddd;
int eeeeeeee;
char *common3;
};
#define somefunc(var) \
printf("%d %c %s\n", var.common1, var.common2, var.common3);
int main()
{
struct str1 var1 = {1,'a',NULL, 4};
struct str2 var2 = {'b',NULL,2,'b'};
struct str3 var3;
var3.common1 = 3;
var3.common2 = 'c';
var3.common3 = NULL;
somefunc(var1);
somefunc(var2);
somefunc(var3);
}
output:
1 a (null)
2 b (null)
3 c (null)
Related
Consider the following code:
typedef struct { char byte; } byte_t;
typedef struct { char bytes[10]; } blob_t;
int f(void) {
blob_t a = {0};
*(byte_t *)a.bytes = (byte_t){10};
return a.bytes[0];
}
Does this give aliasing problems in the return statement? You do have that a.bytes dereferences a type that does not alias the assignment in patch, but on the other hand, the [0] part dereferences a type that does alias.
I can construct a slightly larger example where gcc -O1 -fstrict-aliasing does make the function return 0, and I'd like to know if this is a gcc bug, and if not, what I can do to avoid this problem (in my real-life example, the assignment happens in a separate function so that both functions look really innocent in isolation).
Here is a longer more complete example for testing:
#include <stdio.h>
typedef struct { char byte; } byte_t;
typedef struct { char bytes[10]; } blob_t;
static char *find(char *buf) {
for (int i = 0; i < 1; i++) { if (buf[0] == 0) { return buf; }}
return 0;
}
void patch(char *b) {
*(byte_t *) b = (byte_t) {10};
}
int main(void) {
blob_t a = {0};
char *b = find(a.bytes);
if (b) {
patch(b);
}
printf("%d\n", a.bytes[0]);
}
Building with gcc -O1 -fstrict-aliasing produces 0
The main issue here is that those two structs are not compatible types. And so there can be various problems with alignment and padding.
That issue aside, the standard 6.5/7 only allows for this (the "strict aliasing rule"):
An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
a type compatible with the effective type of the object,
...
an aggregate or union type that includes one of the aforementioned types among its members
Looking at *(byte_t *)a.bytes, then a.bytes has the effective type char[10]. Each individual member of that array has in turn the effective type char. You de-reference that with byte_t, which is not a compatible struct type nor does it have a char[10] among its members. It does have char though.
The standard is not exactly clear how to treat an object which effective type is an array. If you read the above part strictly, then your code does indeed violate strict aliasing, because you access a char[10] through a struct which doesn't have a char[10] member. I'd also be a bit concerned about the compiler padding either struct to meet alignment.
Generally, I'd simply advise against doing fishy things like this. If you need type punning, then use a union. And if you wish to use raw binary data, then use uint8_t instead of the potentially signed & non-portable char.
The error is in *(byte_t *)a.bytes = (byte_t){10};. The C spec has a special rule about character types (6.5§7), but that rule only applies when using character type to access any other type, not when using any type to access a character.
According to the Standard, the syntax array[index] is shorthand for *((array)+(index)). Thus, p->array[index] is equivalent to *((p->array) + (index)), which uses the address of p to compute the address of p->array, and then without regard for p's type, adds index (scaled by the size of the array-element type), and then dereferences the resulting pointer to yield an lvalue of the array-element type. Nothing in the wording of the Standard would imply that an access via the resulting lvalue is an access to an lvalue of the underlying structure type. Thus, if the struct member is an array of character type, the constraints of N1570 6.5p7 would allow an lvalue of that form to access storage of any type.
The maintainers of some compilers such as gcc, however, appear to view the laxity of the Standard there as a defect. This can be demonstrated via the code:
struct s1 { char x[10]; };
struct s2 { char x[10]; };
union s1s2 { struct s1 v1; struct s2 v2; } u;
int read_s1_x(struct s1 *p, int i)
{
return p->x[i];
}
void set_s2_x(struct s2 *p, int i, int value)
{
p->x[i] = value;
}
__attribute__((noinline))
int test(void *p, int i)
{
if (read_s1_x(p, 0))
set_s2_x(p, i, 2);
return read_s1_x(p, 0);
}
#include <stdio.h>
int main(void)
{
u.v2.x[0] = 1;
int result = test(&u, 0);
printf("Result = %d / %d", result, u.v2.x[0]);
}
The code abides the constraints in N1570 6.5p7 because it all accesses to any portion of u are performed using lvalues of character type. Nonetheless, the code generated by gcc will not allow for the possibility that the storage accessed by (*(struct s1))->x[0] might also be accessed by (*(struct s2))->x[i] despite the fact that both accesses use lvalues of character type.
Short version:
Suppose I have two structs:
struct charPtrWithLen
{
size_t len;
char * charPtr;
}
struct voidPtrWithLen
{
size_t len;
void * voidPtr;
}
Is there a way to cast voidPtrWithLen into charPtrWithLen and vice-versa, or even better, implicitly convert one into the other, much the same way that a char * and a void * can be readily cast and implicitly converted between each other?
Put another way:
I am trying to write all my C so that all pointers to arrays bring their size information with them. I am also trying to write generic functions using void pointers where applicable to keep operations which are essentially identical, well, identical. I am looking for a way to pass the typed-pointer-containing 'sized-array' structs into the generic functions taking void-pointer-containing 'sized-array' arguments.
Long version, with involved example:
So, void pointers are wonderfully flexible, so I can do this:
int foo(void * ptr, size_t dataLen);
/* ... */
char * c;
size_t c_n;
/* ... */
foo(c, c_n);
/* ... */
int * i;
size_t i_n;
/* ... */
foo(i, i_n);
But since the pattern of "pointer to arbitrary length array, plus size there-of" is so common, suppose at some point I get tired of specifying my various functions in terms of pairs of arguments, pointer and length, and instead I start to code with such pairs encapsulated in a struct instead:
typedef struct
{
size_t v_n;
void * v;
}
pointerWithSize;
/* ... */
int foo(pointerWithSize);
So far so good. I can always assign my "char * c" or "int * i" into the pointerWithSize's "void * v" with minimal difficulty. But when you do this long enough, using the same pattern, you run into the following problem: Soon enough you have a bunch of general functions which work with the data agnostically, and are thus happy to take void pointers, for example things like:
pointerWithSize combinePointersWithSize(pointerWithSize p1, pointerWithSize p2);
int readFromStream(FILE * readFromHere, pointerWithSize * readIntoHere);
But you also end up with functions which are inherently intended for specific data types:
size_t countOccurancesOfChar(pointerWithSize str, char c);
int summate(pointerWithSize integers);
And then you end up with the annoyance of having to do casts inside the latter category of functions. E.g. you end up with stuff like this:
/* This inside countOccurancesOfChar */
if(((char * )str.m)[i] == c) {
/* ..or this inside summate: */
sum += ((int * )integers.m)[i];
So you get to a point where you have a lot of functions which operate specifically on "strings with size", and in all of those cases, you don't want to have to much around with void pointers. So instead, in those cases you start doing stuff like this:
typedef struct
{
size_t v_n;
char * v;
}
stringWithSize;
/* ... */
size_t countOccurancesOfChar(stringWithSize str, char c);
int parseFormatting(stringWithSize str, struct someFormat_t foo);
Which is great, because now all the string related code doesn't need to be cluttered with casts. BUT, now I can't use my wonderful generic function combinePointersWithSize to concatenate my strings contained within the stringWithSize, in a way that's as syntactically clean, as I could if I was still writing my functions in terms of two separate arguments for each pointer-and-size pair.
To finish up the illustration:
pointerWithSize combinePointersWithSize(pointerWithSize p1, pointerWithSize p2);
void * combineAlternative(void * p1, size_t p_n1, void * p2);
/* ... */
stringWithSize a, b, c;
/* ... */
/* This doesn't work, incompatible types: */
c = combinePointersWithSize(a, b);
/* But this works, because char * can be passed into void * parameter. */
c.v_n = a.v_n + b.v_n;
c.v = combineAlternative(a.v, a.v_n, b.v, b.v_n); /* Works fine. */
Possible Solutions I've Considered:
1: Don't write my functions with those structs as arguments, instead write them with individual pair arguments. But this is a big part of what I want to avoid in the first place - I like the 'cleanness' and clarity of intent that having a size_t and a pointer bundled in one struct represents.
2: Do something like this:
stringWithSize a, b, c;
/* ... */
pointerWithSize d;
d = combinePointersWithSize((pointerWithSize){.v=a.v, .v_n=a.v_n}, (pointerWithSize){.v=b.v, .v_n=b.v_n})
/* and then do either this: */
c.v = d.v;
c.v_n = d.v_n;
foo(c);
/* ..or this: */
foo((stringWithSize){.v=d.v, .v_n=d.v_n});
..but I think most would agree, this is also as bad or worse as the original problem of casting within the library functions. On the surface it looks worse, because it offloads the casting burden to the client code instead of library code which can hopefully be fairly stable after being implemented/completed (incl. testing/etc). On the other hand, if you did keep every function defined in terms of the void * containing pointerWithSize, you could end up forcing similar casts to the kind you're doing inside your own functions, elsewhere in their code, and worse, you're losing the advantage of the compiler yelling at you, because now the code is carrying everything within the same pointerWithSize struct.
I'm also concerned about how many compilers out there have the ability to optimize the first of the two variants of this solution away (where 'd' servers as merely a temporary result holder.
3: Union-of-pointers. Instead of my prior pointerWithSize example, I would do:
typedef union
{
void * void;
char * char;
int * int;
/* ...and so on... */
}
rainbowPointer;
typedef struct
{
size_t v_n;
rainbowPointer v;
}
pointerWithSize;
At first glance this is almost good enough. However, I very frequently end up wanting to store arrays of some struct which is specific to the program I'm working on inside this "pointer with size" construct, and in those cases, a predefined union of pointer types would be useless to me, I'd still be right back at this problem.
4: I could write wrapper functions for each permuted pointer type. I could EVEN write function-like macros to define each of these pointer-with-size struct types, which would in the same swoop generate the wrapper functions. For example:
#define pointerWithSizeDef(T, name) \
typedef struct \
{ \
size_t v_n; \
T * v;
} \
name; \
foo_ ## name (name p1) \
{ \
/* generic function code defined in macro */ \
/* Or something like this: */ \
foo((pointerWithSize){.v=p1.v, .v_n=p1.v_n});
};
/* Then, stuff like this: */
pointerWithSizeDef(char, stringWithSize)
My intuition is that sooner or later this method would become unwieldy.
5: If there is a mechanism with no performance impact, but which is unappealing otherwise, I could write my generic functions as function-like macros, which in turn invoke the underlying actual function:
int foo_actual(void * v, size_t v_n);
#define foo(p) \
foo_actual(p.v, p.v_n);
..or even something like this, to replace casting syntax:
#define castToPointerWithSize(p) \
((pointerWithSize){.v=p.v, .v_n=p.v_n})
/* ... */
stringWithSize a;
foo(castToPointerWithSize(a));
But as these examples for possible-solution-#5 show, I can't actually think of a way to do this that wouldn't quickly become a possible problem (e.g. if someone wanted to place a function call which returned a pointerWithSize in place of 'p' in the above examples - you'd be running the function twice, and it wouldn't be at all obvious from the code.
So I don't think any of the solutions I've thought of are really sufficient for my usecase, so I'm hoping some of you know of some C syntax or mechanism I could take advantage of here to make it easy to cast/"cast" between two structs which are identical save for the pointer type of one of their members.
Firstly, any kind of "actual" casting isn't going to be allowed per the letter of the standard, because C makes no guarantee at all that all pointers have the same format. A cast from some arbitrary pointer type to a void pointer is allowed to involve a conversion of representation (that gets reversed when you cast it back in order to access the data), including possibly to a different size of pointer or a pointer existing in a separate address space. So a simple reinterpretation of a bit pattern to change pointer type is not safe; void*'s bit pattern isn't guaranteed to mean anything in particular, and the bit patterns of other types aren't guaranteed to be related in any particular way. (How many systems actually take advantage of this, I have no idea.)
Since the explicit conversion between void* and other types has to exist somewhere, using whole-value conversion is probably the safest idea. What you could do is define a macro to quickly and easily generate "cast functions" for you, e.g.:
#define GEN_CAST(NAME, FROM_TYPE, TO_TYPE) \
static inline TO_TYPE NAME(FROM_TYPE from) { \
return (TO_TYPE){ .v=p.v, .v_n=p.v_n }; \
}
GEN_CAST(s_to_v, stringWithSize, pointerWithSize)
GEN_CAST(v_to_s, pointerWithSize, stringWithSize)
...that you can then use in place of the cast operator in expressions:
stringWithSize a, b, c;
pointerWithSize d;
d = combinePointersWithSize(s_to_v(a), s_to_v(b));
foo(v_to_s(d));
A good compiler should recognise that on common platforms the conversion function is an identity operation, and remove it entirely.
You should be able to cast one to another by converting one to a pointer, casting it to a pointer of the other type, and dereferencing it. This will work in reverse too.
struct charPtrWithLen
{
size_t len;
char * charPtr;
};
struct voidPtrWithLen
{
size_t len;
void * voidPtr;
};
int main() {
struct charPtrWithLen cpwl = {.len = 6, .charPtr = "Hello"};
struct voidPtrWithLen vpwl = *(struct voidPtrWithLen *)&cpwl;
return 0;
}
Note this will only work as long as the struct layout is the same for both structs.
I have been going through the Atmel library USB for AT91SAM7 and there is something I don’t understand. Endpoint is a structure defined as follows:
typedef struct {
volatile unsigned char state;
volatile unsigned char bank;
volatile unsigned short size;
Transfer transfer; //thus Endpoint contains an instance of "Transfer"
} Endpoint
point;
And Transfer itself is a structure as follows:
typedef struct {
char *pData;
volatile int buffered;
volatile int transferred;
volatile int remaining;
volatile TransferCallback fCallback;
void *pArgument;
} Transfer;
And TransferCallback is a function with the following prototype:
typedef void (*TransferCallback)(void *pArg, unsigned char status, unsigned int transferred, unsigned int remaining);
also two pointers have been defined as the following:
Endpoint *pEndpoint = &(endpoints[bEndpoint]);
Transfer *pTransfer = &(pEndpoint->transfer);
I want to know why such a way to call the function TransferCallback is valid:
((TransferCallback) pTransfer->fCallback) (followed by the required arguments passed )
But this is not valid:
((TransferCallback)pEndpoint->transfer->fCallback)?
how could I directly call TransferCallback without using a pointer such as pTransfer in between?
I tried a number of combinations but none worked.
Note that Endpoint does not have a pointer to Transfer member (*Transfer), but a Transfer member. In machine terms, rather than a single word of memory within each Endpoint being used as a pointer to a Transfer, all the fields of the Transfer member are stored directly inside the memory allocated for the Endpoint.
To cut to the chase, what you need is:
((TransferCallback)pEndpoint->transfer.fCallback)
Regarding the title to the OP: how to call a function by pointer in C
+1 to Alex's answer of your question about How, but there is another point that can be made in the interest of knowing Why choose a function pointer over just providing the normal function name in the first place; Function pointers are especially useful in C* (see *) when you have a collection of functions that are similar in that they contain the same argument list, but have different outputs. You can define an array of function pointers, making it easier, for example, to call the functions in that family from a switch, or a loop, or when creating a series of threads in a pool that include similar worker functions as arguments. Calling an array makes it as simple as changing the index of the pointer to get the specific functionality you need for each unique case.
As a simple example, the two string functions strcat() and strcpy() have the argument list: (char *, const char *), therefore, may be assigned to an array of function pointers. First create the function pointer array:
char * (*pStr[2])( char *a, const char *b);` //array of function pointers pStr[]
Then, make the assignements of strcat and strcpy to the array:
void someFunc(void)
{
pStr[0] = strcat; //assign strcat to pointer [0]
pStr[1] = strcpy; //assign strcpy to pointer [1]
}
Now, strcat() or strcpy() can be called as:
int main(void)
{
char a[100]="kjdhlfjgls";
char b[100]="kjdhlfjgls";
someFunc();//define function pointers
pStr[0](a, "aaaaaaaa"); //strcat
pStr[1](b, "aaaaaaaa"); //strcpy
return 0;
}
Example output:
This is just a simple example. It does not explore the full extent of usefulness function pointers can provide, but illustrates another reason why functions pointers may be preferred in some situations.
* This illustration is targeted only to C, as opposed to C++, where qualities of inheritance and polymorphism inherent to that language would make this suggestion unnecessary.
Assuming I have a structure such as:
typedef struct
{
char * string1;
char * string2;
} TWO_WORDS;
such that all the fields are of the same type, and my main has
TWO_WORDS tw;
can I reference string1 with tw[0] and string2 with two[1]? If so:
is this part of the c standard?
do i have to cast the struct to an array first?
what about fields which are different sizes in memory
what about fields which are different types but the same size?
can you do pointer arithmetic within a structure?
-
I got pretty close with this construct:
((char**)&tw)[0];
As an example:
int main()
{
typedef struct
{
char * string1;
char * string2;
} TWO_WORDS;
TWO_WORDS tw = {"Hello", "World"};
printf("String1: %s\n", ((char**)&tw)[0]);
printf("String2: %s\n", ((char**)&tw)[1]);
return 0;
}
It is not guaranteed to work, as the compiler may add padding between fields. (Many compilers have a #pragma that will avoid padding of structs)
To answer each of your questions:
is this part of the c standard? NO
do i have to cast the struct to an array first? YES
what about fields which are different sizes in memoryThis can be done with even more "evil" casting and pointer-math
what about fields which are different types but the same size?This can be done with even more "evil" casting and pointer-math
can you do pointer arithmetic within a structure?Yes (not guaranteed to always work as you might expect, but a structure is just a piece of memory that you can access with pointers and pointer-math)
As #ouah points out, no you can't do it quite that way. However, you could:
typedef union
{ char *a[2];
struct
{ char *string1;
char *string2;
} s;
} TWO_WORDS;
TWO_WORDS t;
t.a[0] = ...;
t.a[1] = ...;
t.s.string1 = ...;
t.s.string2 = ...;
No, you cannot use index access to struct data members, unless you take specific steps to emulate it.
In C++ this functionality can be emulated by using a C++-specific pointer type known as "pointer-to-data-member". C language has no such type, but it can in turn be emulated by using the standard offsetof macro and pointer arithmetic.
In you example it might look as follows. First, we prepare a special offset array
const size_t TW_OFFSETS[] =
{ offsetof(TWO_WORDS, string1), offsetof(TWO_WORDS, string2) };
This offset array is later used to organize index access to struct members
*(char **)((char *) &tw + TW_OFFSETS[i]);
/* Provides lvalue access to either `tw.string1` or `tw.string2` depending on
the value of `i` */
It doesn't look pretty (although it can be made to look better by using macros), but that's the way it is in C.
For example, we can define
#define TW_MEMBER(T, t, i) *(T *)((char *) &(t) + TW_OFFSETS[i])
and use it in the code as
TW_MEMBER(char *, tw, 0) = "Hello";
TW_MEMBER(char *, tw, 1) = "World";
for (int i = 0; i < 2; ++i)
printf("%s\n", TW_MEMBER(char *, tw, i));
Note that this approach is free from the serious issues present in the solution based on reinterpreting the struct as char*[2] array (regradless of whether it is done through a union or through a cast). The latter is a hack, illegal from the formal point of view and generally invalid. The offsetof-based solution is perfectly valid and legal.
can I reference string1 with tw[0] and string2 with two[1]?
No you cannot in C, tw is a structure not a pointer.
The constraints of the [] operator require one of the operand to be of a pointer type.
To access string1, you can use this expression: tw.string1
Nope, you can't do that in C. You can only access struct members in C via their names.
What you can do is build an array that has pointers to the same strings as those in your struct, and then use indexes for the array.
But why would you want to do that? What is the problem you're actually trying to solve with this?
You can use ((char **)&tw)[0] to do it, if you really wanted to, but not tw[0].
If one has a struct which starts with fields that are all of the same type, one may declare a union which includes a struct of that type as well as an array of the appropriate field type. If one does this, reading or writing an element of the array will read or write the appropriate struct member. This behavior will work on all implementations I know of, and I believe it is portable if all the fields are the same size.
struct quad_int {int n0; int n1; int n2; int n3;}
union quad_int_union {struct pair p; int n[4];}
union quad_int_union my_thing;
my_thing.n[0] is synonymous with my_thing.p.n0
my_thing.n[1] is synonymous with my_thing.p.n1
etc.
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.