lvalue required error while compiling - c

I have a struct
typedef struct _scaffale {
int NumeroScaffale;
scaffali * succ;
copia** pos;
} scaffale;
in which I have an array of the struct copia. The error comes in the following code:
copia** temp;
temp=scaff->pos;
(temp+controllo)=nuovo->copie;
in the third row to be precise. The question is: why this line give me that error while in the following code in which I use the same construct it is perfectly allowed:
while(i<=MAXLIBRI){
if ((temp+i)!=NULL) {
i=i+1;
}
else break;
}

(temp+controllo) is an rvalue. By that I mean it's a computed value, not a location to put something. I'm guessing that what you really meant is *(temp+controllo) = nuovo->copie; instead, which would have assigned nuovo->copie into the location identified by temp+controllo.
For an analogy, if i is an int, you can say i = 3, but you can't say (i+1) = 3. I hope it's obvious why.

(temp+controllo) is a computed value, and doesn't follow the language rules for being a proper l-value which is a fancy way of saying "you can't put it on the left of an assignment operator".

Related

Affecting a "static" struct in another struct in heap

So I solved my problem, wasn't that hard, but I'm wandering why the first version wasn't working.
So here, an example of my problem :
typedef struct a {
int i;
} A;
typedef struct b {
int i;
A a;
} B;
typedef B * PB;
PB create_B(int ia, int ib) {
PB b = malloc(sizeof(B));
b->i = ib;
b->a = {ia};
}
I get an error from the compiler saying :
"error: expected expression before ‘{’ token"
at line: b->a = {ia};
But i don't really get what is the problem.
I solved it casting the structure :
PB create_B(int ia, int ib) {
PB b = malloc(sizeof(B));
b->i = ib;
b->a = (A){ia};
}
But the types are well defined no ? I mean it's kind of obvious to me that {ia} is of type A since b->a is of type A aswell.
I am probably wrong on this last saying (compiler is probably right). So if you have an example where this situation isn't obvious and really need a cast, it would be really appreciated, or jut an explanation at least.
Thank you for your time.
Barioth
PS :
I could have done that too i guess
PB create_B(int ia, int ib) {
PB b = malloc(sizeof(B));
*b = (B){ib, {ia}};
}
But i still need a cast...
{ia} is not an expression in C and cannot be used in an expression statement.
{ia} is part of a syntax for definitions. In a definition, a list of initial values may be given in braces after an =. (And the braces may be omitted when initializing a scalar object.) This is a special syntax for initializing in a definition and is not an assignment like using = in an expression.
(A){ia} is an expression; it is a construct called a compound literal. After a type name in parentheses, initial values are given inside braces. This creates an object of the stated type. That object may then be used in an expression, such as as the right operand of an assignment.

Pointer to array structure

I have a small program which when compiling throws me the following errors
error #2168: Operands of '+' have incompatible types 'struct agenda' and 'int'.
error #2113: Left operand of '.' has incompatible type 'int'.
error #2088: Lvalue required.
This is the code that I have done
#include <stdio.h>
struct agenda{
int order, cellular;
char name[30], last_name[30], street[30], city[30], mail[50];
}contact[10];
int main(void)
{
struct agenda *ptrcontact;
ptrcontact = &contact[0];
(*ptrcontact+3).order = 3;
printf("\n\n %d", (*ptrcontact).order);
return 0;
}
because it throws these errors and how to fix them?
You need to change
(*ptrcontact+3).order = 3;
to
ptrcontact[3].order = 3;
or, at least,
(*(ptrcontact+3)).order = 3;
or,
(ptrcontact + 3)->order = 3;
Otherwise, as per the precedence rule, * has higher precedence over +, causing the error.
Just to add to that, ptrcontact is a pointer ( to struct agenda) and can be used as an operand to + operator.
OTOH, *ptrcontact is of type struct agenda and cannot be used as an operand to + operator.
You are dereferencing the pointer which yields the struct and obviously you can't add anything to that. Dereference operator has the highest priority, you need to do it like this: (*(ptr + 3)).order or use the arrow instead of star dot: (ptr + 3) -> order
Your problem here is operations priority:
(*ptrcontact+3).order = 3;
This derefers ptrcontract and then tries to add number to dereferred structure. Which gives you exact situation you report.
My recommendations:
Either avoid address ariphmetics in such cases. Operate array indexes.
int baseIndex = 0;
contact[baseIndex + 3].order = 3;
Or if you really have to do so, hide address arithmetic from outside:
(pcontact + 3)->order = 3;
And finally learn C language operations priority or, to do it once (but some C people don't like C++), C++ operations priority
the error is in the lines
(*ptrcontact+3).order = 3; and printf("\n\n %d", (*ptrcontact).order);. In this instructions use -> instead of . the errors will be solved.

Pointers casting in C "on the fly"

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;

Pointer and Structure problems

I am suppose to be creating a memory map of this program for my class, but when I try to compile it, I get an error:
invalid operands to binary expression ('double *' and 'double *')
I am a student, please do not edit the code to print out memory locations, I need to write that myself.
main()
{
double testd;
int testi;
FILE *fpt;
struct frog {
double *x, y;
}frog;
struct frog turtle, *apple, tv[3];
testi = 2;
apple = &turtle;
apple->x = &testd
*(turtle).x = 7.3; //this is where im getting the error.
(*apple).y = 3.6;
turtle.y = 1.5;
for (testi = 0; testi < 3; testi++)
tv[testi].x = &(tv[(testi+1)%3].y);
*(tv[1].x) = 6.4;
}
You are missing the ; at the end of the previous line.
You are not wrong to dereference *(turtle).x instead of *(turtle.x). The . operator has higher precedence than the * operator, meaning those two statements are equivalent and you don't even need parentheses: you could just do *turtle.x.
Check out this site for precedence ordering.
You are missing the ; at end of the previous line.
The compiler then interprets the * at the beginning of the line as a multiplication symbol and complains because that doesn't work out so well.
You simply forgot ; after apple->x = &testd statement.
On a side note, in C you have to say struct before a structure, and main function is supposed to return an integer. You also need to include header files with declarations of data structures and functions that you are using (i.e. stdio.h). Not to mention that // comment style is C99, and C programmers don't really use it.. /* */ comments are awesome.

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