I have the following question:
Is it possible to cast pointer "on the fly", without additional variable assignment? Let's see some example:
typedef struct
{
uint8_t TimeSlot;
uint8_t TimeTick;
}Menager_t;
void SomeFunction(void* vp)
{
(Menager_t *)vp->TimeSlot = 0; //Error, request for member 'TimeSlot'
//in something not a structure or union
}
So, this can be solved by assign void pointer to temporary pointer inside of function, like this:
void SomeFunction(void* vp)
{
Menager_t *temp = vp;
temp->TimeSlot = 0;
}
But i must say that this solution does not satisfy me and looks dirty form me (omitting fact of 128 bytes RAM memory on uC I'm programming) and furthermore I remember that i was doing such things in past...
I'm asking You guys kindly for help in that :)
Regards!
PS: GCC 4.7.2 in use
You forgot to add some parenthesis.
((Menager_t *)vp)->TimeSlot = 0;
-> binds more strongly that (cast) operator, therefore vp->TimeSlot is evaluated first.
-> has higher precendence than the cast (see, e.g., here: http://en.cppreference.com/w/c/language/operator_precedence), so the compiler tries to access TimeSlot on a void *. Add parentheses to make the cast happen first:
((Menager_t *)vp)->TimeSlot = 0;
Related
I have written a C program and I'm compiling with GCC (for an arm MCU).
I have a function that changes the address of void pointer to point to another void,and so on.
The problem is that the Linker/Compiler think that the code is unused and discard it.
I have tried attribute(( used )) but that didn't work.
The voids and code are in separate .h/.c file from the main.h/c but are included in the main.c
Code:
void q2_h(void (*ptr)(uint8_t), uint8_t a) {
if (a == 3) {
ptr = (void*) q3_h;
} else {
ptr = (void*) q22_h;
}
}
Definition:
void q2_h(void (*ptr)(uint8_t), uint8_t a)__attribute__((used));
Input Pointer:
void (*ptr)(void*,uint8_t);
which is not completely right because the (uint8_t) is missing but I'm not sure about the syntax.
So if if you have any idea on how to sol
Problems:
The code changes a local variable, not the function pointer in the calling code. So it is not "seemingly dead", it's truly dead. Instead of fiddling around with attributes, listen to what your compiler is trying to tell you.
Always use typedef when dealing with function pointers, it would have made the bug more obvious.
You cannot cast a function pointer to a void pointer or vice versa. void* is only a generic pointer type for object pointers. You shouldn't need to cast at all, or your code is attempting fishy invalid pointer conversions, which would be a bug.
Corrected code might look something like:
typedef void func_t (uint8_t);
void q2_h(func_t** ptr, uint8_t a) {
if (a == 3) {
*ptr = q3_h;
} else {
*ptr = q22_h;
}
}
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.
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.
Let's say that any C function has a pointer already declared, but not assigned any value yet. We will int for our examples.
int *ptr;
The goal of the function is not to assign ptr any dynamic memory on the heap, so no malloc call. Instead, we want to have it point to an array of fixed size n. I know I could accomplish this like so:
int arr[n];
ptr = arr;
However, the code could get very messy and hard to read if we need to do this many times in a function, ie, a struct of many pointer fields all need to point to an array of fixed length. Is there a better way to accomplish this in one line? I was thinking of something similar to below, but it looks too ambiguous and uncompilable:
int *ptr;
// Many other things happen in between...
ptr[n];
***EDIT***
Here, the below additional information may help guide some more answers (not saying that the current answers are not fine). In my use case, the pointers are declared in a struct and, in a function, I am assigning the pointers to an array. I want to know if there is a simpler way to accomplish this than in the below code (all pointers to point to fixed-length array):
struct foo {
int* a;
short* b;
char* c;
...
};
void func(void) {
struct foo f;
int n = ...;
int tempArr1[n];
f.a = tempArr1;
short tempArr2[n];
f.b = tempArr2;
char tempArr3[n];
f.c = tempArr3;
...
}
You cannot declare an array and assign it to an existing pointer in a single declaration. However, you can assign an array pointer to a newly declared pointer, like this:
int arr[n], *ptr = arr;
If you insist on staying within a single line, you could use an ugly macro, like this:
#define DECL_ASSIGN_INT_ARRAY(name,size,pointer) int name[(size)]; pointer = name;
The clarity of this one-liner is far lower than that of a two-line version from your post, so I would keep your initial version.
EDIT (in response to the edit of the question)
Another option is to create an unused pointer variable in a declaration, and assign your pointer in an initializer, like this:
void func(void) {
struct foo f;
int n = ...;
int tempArr1[n], *tempPtr1 = f.a = tempArr1;
short tempArr2[n], *tempPtr2 = f.b = tempArr2;
char tempArr3[n], *tempPtr3 = f.c = tempArr3;
...
}
This seems like a clear case where you're in need of some refactoring. Take the similar statements, extract them into a new function (by passing a reference to the struct and the data you want the struct fields to point to) and give this new function a meaningful name.
This is probably more maintainable and readable than some fancy pointer arithmetic shortcut that you'll forget about in a few weeks or months.
The difference between ptr and arr in you example is you can change ptr's value. So I guess you want to move ptr through the array.
So how about this:
int arr[n], id=0;
And you change the value of id and use arr+id as ptr.
I guess the way to do this is to use a macro. Something like (untested)
#define autoptr(name,size) int Arrayname[size]; name = Arrayname;
I'm not clear why this is helping I think it might "look ugly" but will be easier to maintain without the macro. In general, hiding what you are actually doing is a bad thing.
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.