I want to access members of a structure from void pointer inside a structure, I have tried the following code but it is giving error as "expected identifier before ‘(’ token". what should I change in printf statement? Thanks in advance.
#include "stdio.h"
struct
{
int date;
char *name;
}test;
struct
{
void *check;
}massage;
main()
{
test.date=21;
test.name="Nilesh";
massage.check =&test;
printf("date - %d , name - %s\n",massage.((struct test *)check)->date,massage.((struct test *)check)->name);
}
struct // anonymous struct type
{
int date;
char *name;
} test;
The above statement defines an anonymous struct type and creates a variable test of this struct type which has no name. Similarly, the below statement defines an anonymous struct type and creates a variable massage of this type -
struct // anonymous struct type
{
void *check;
} massage;
The typecast operator must have a type in the parentheses (type), not a variable name. Therefore, you must give the first struct a name (tag) so as to use the typecast operator. Also, the result of a typecast operator is an r-value and therefore it cannot be used with member selection .(dot) operator (it should be the name of the member). Therefore, the typecast operator should be applied after the value is fetched from the structure. Therefore, the following expression is wrong -
massage.((struct foo *)check)->date
// |____________________|
// |
// this should be the member name but it
// evaluates to a r-value - the result of
// the typecast operator assuming struct tag
// is foo
// it should instead be
((struct foo *)massage.check)->date
// dot operator has higher precedence than typecast
// so the struct member check is fetched first and
// it is typecast to type (struct foo *)
I suggest the following changes -
// standard headers should be
// enclosed in angle < > brackets
#include <stdio.h>
// give the structure a name so it can be
// used in typecasting
struct foo {
int date;
char *name;
} test;
// anonymous struct type
struct {
void *check;
} massage;
// return type of main should be int and
// parameter list should contain void
int main(void) {
test.date = 21;
test.name = "Nilesh";
massage.check = &test;
// fetch the struct member check and then
// apply typecast operator
printf("date - %d , name - %s\n", ((struct foo *)massage.check)->date,
((struct foo *)massage.check)->name);
return 0;
}
In your expression:
massage.((struct test *)check)->date
// ^^^ is variable not a data-type
there are two mistakes:
You can't type case into a variable, in your code test is a variable not a type so (struct test *) is wrong expression. You should name the user-defined type (as I have suggested below).
You are applying typecasting without accessing massage's pointer member. So in expression (struct test *)check, actually "check" is unknown variable. compiler will error you "check" is undeclared variable (thought test is not a datatype but the order of applying type casting is conceptually wrong).
I am suggesting a couple of correction try with it:
Name the stuct e.g. newtype
struct newtype // notice I given name to user defined datatype
{
int date;
char *name;
}test;
Then correct second and third argument in printf function as below
((struct newtype *)massage.check)->date
// ^^^^^^^^^^^^^^ notice
Similarly third argument in printf. First access member then type cast to correct type.
For full code refer Ajay's answer.
The struct definition is not want you want -- it defines an object test of an unnamed struct type. Try
struct testType
{
int date;
char *name;
} test;
and then cast to (testType *).
Related
I defined a structure called coordonnees declared as a pointer, I want to append values to the pointer a_visiter but it's not working. How can I fix that?
Here is the struct code:
typedef struct couple
{
int ligne;
int colonne;
}*coordonnees;
int main()
{
coordonnees a_visiter;
a_visiter=(coordonnees)malloc(DIMENSION*4*sizeof(struct couple));
int p=0;
etc ...
}
void voisin_egaux(char matrice[][DIMENSION+1],int x, int y,coordonnees **a_visiter,int *p)
{
if (matrice[x][y]==matrice[x+1][y]){
(a_visiter+(*p))->ligne=x+1;
(a_visiter+(*p))->colonne=y;
++(*p);
}
I get as an error: request for member ligne in something not a structure or union.
This parameter declaration
coordonnees **a_visiter
is equivalent to
struct couple ***a_visiter
Thus the expression
(a_visiter+(*p))
has the above pointer type that does not point to an object of the structure type.
To make this code semantically valid
(a_visiter+(*p))->ligne=x+1;
(a_visiter+(*p))->colonne=y;
the parameter should be declared like
coordonnees a_visiter
Otherwise you need to write
( **a_visiter+(*p))->ligne=x+1;
( **a_visiter+(*p))->colonne=y;
For a Risk-like game I have a struct for each region, each of which need to have a list of associated regions that troops can move into from the mother region.
In theory, it would look like
typedef struct {
char* name;
region_t* connections;
} region_t;
However, this is of course impossible due to the fact that region_t doesn't exist before the parser reaches the type region_t*. Therefore I have opted to use void* in place of region_t*.
typedef struct {
char* name;
void* connections;
} region_t;
MiddleEast.connections = malloc(6 * sizeof(void*));
MiddleEast.connections = &SouthernEurope;
MiddleEast.(connections + 1) = &Egypt;
Using the region_ts MiddleEast, SouthernEurope, and Egypt, I can set the first connection to Southern Europe successfully, but when I try to set .(connections + 1) to &Egypt I get the compiler error
error: expected identifier before ‘(’ token
How do I properly access the next memory address?
The solution is not void *, it's properly using structs.
structs with a name can be referenced inside themselves. The type doesn't exist, but the named struct does, so you can write:
typedef struct region{
char* name;
struct region* connections;
} region_t;
You want to create an array of void pointers, not an array of voids. You want to iterate over void pointers.
typedef struct {
char* name;
void **connections;
} region_t;
MiddleEast.connections = malloc(6 * sizeof(void*));
MiddleEast.connections[0] = &SouthernEurope;
MiddleEast.connections[1] = &Egypt;
free(MiddleEast.connections);
is of course impossible due to the fact that region_t doesn't exist before the parser reaches the type region_t*.
You can't forward declare a typedef, but you can do that with structure.
typedef struct region_s {
char *name;
struct region_s *connections;
} region_t;
Forward declaration is common in C code in constructing linked lists and similar. The sizeof(struct region_s *) is known, the struct region_s pointer size is known before the struct region_s is defined, so you can:
// forward declaration
struct region_s;
// pointer is ok
struct region_s *regionpointer;
// we can define the structure after using a pointer
struct region_s {
// you can even point to yourself
struct region_s *regionpointer;
};
// typedef separated for readbility
typedef struct region_s region_t;
error: expected identifier before ‘(’ token
MiddleEast.(connections + 1) = &Egypt;
The . is member operator; it gets the member of a structure. The string after . is taken as a symbol. As you can see, there is no member inside MiddleEast structure named (connections (exactly, using space as separator), as such name is disallowed. You want:
MiddleEast.connections + 1 = &Egypt;
Which will still not work, as the left side of = is the value of the pointer inside MiddleEast.connections array. You can't assign this value; it is a result of an addition. (the same you can't int a; a + 5 = 43;). What you want is to assign the value of the second element inside MiddleEast.connections array to the value of &Egypt. So you need to deference the pointer value.
*(MiddleEast.connections + 1) = &Egypt;
Or shorter and way more readable, as a[b] is equal to *(a + b):
MiddleEast.connections[1] = &Egypt;
Jokingly: Please never:
1[MiddleEast.connections] = &Egypt;
The MiddleEast.connections is an "integral"/whole/standalone part, that you can't separate.
Note that doing:
MiddleEast.connections = malloc(6 * sizeof(void*));
MiddleEast.connections = &SouthernEurope;
just leaks memory, as you can't no longer free(MiddleEast.connections) free the memory.
I've come across this strange way to define a structure in C and I cannot find anywhere what this really is?
typedef struct {
int val;
} *Name;
What is the difference to this?
typedef struct {
int val;
} Name;
I see however that I have to use "->" on the first and "." on the second, but what is really the difference?
In the first case
typedef struct {
int val;
} *Name;
the name Name is declared as an alias for the type pointer to an unnamed structure.
You can use this pointer type for example the following way
Name ptr = malloc( sizeof( *ptr ) );
and then you can write for example
ptr->val = 10;
or
( *ptr ).val = 10;
That is in this declaration there is declared the pointer ptr of the type Name and dynamically created an object of the structure and the pointer points to this dynamically created object.
In the second case
typedef struct {
int val;
} Name;
the name Name is declared as an alias for the unnamed structure itself.
To declare an object of this type you can just write
Name name;
and then
name.val = 10;
or just
Name name = { 10 };
and an object of the structure type will be created.
Or if you want to allocate an object of the structure type dynamically you can write
Name *ptr = malloc( sizeof( Name ) );
To make it more clear here are another examples of using typedef.
typedef int A[10];
this typedef declares the name A as an alias for the array type int[10].
you can write after that
A a;
This declaration declares array object a of the type A that is equivalent to int[10].
This declaration
typedef int ( *A )[10];
declares the name A as an alias to the type pointer to an array of type int[10].
This declaration can be used for example the following way
int a[10];
A ptr_a = &a;
When you write
typedef struct {
int val;
} Name;
you're saying "the name Name now refers to a struct with one element, an int named val."
When you write
typedef struct {
int val;
} *Name;
the star changes the meaning so that this says "the name Name now refers to a pointer to a struct with one member, an int named val." This is why you need to use the arrow operator rather than a dot: in the first case, Name is a type that's an honest-to-goodness structure, and in the second Name is a type that's a pointer to a structure.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main()
{
struct emp
{
struct address
{
int a;
};
struct address a1;
};
}
This code shows a warning:-
warning : declaration does not declare anything (enabled by default)
Where as the following code shows no warning
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main()
{
struct emp
{
struct address
{
int a;
}a1;
};
}
Why 'warning' is displayed in the first code only?
The reason why the compiler is showing the warning is because it doesn't see a name for the variable of type address you defined for the emp struct, even though you do declare something using address on the next line, but I guess the compiler is not smart enough to figure that out.
As you showed, this produces a warning:
struct emp {
struct address {}; // This statement doesn't declare any variable for the emp struct.
struct address a1;
};
But not this:
struct emp {
struct address {} a1; // This statement defines the address struct and the a1 variable.
};
Or this:
struct address {};
struct emp {
struct address a1; //the only statement declare a variable of type struct address
};
The struct emp {} doesn't show any warnings since this statement is not inside a struct defintion block. If you did put it inside one of those then the compiler will show a warning for that as well. The following will show two warnings:
struct emp {
struct phone {};
struct name {};
};
The reason the warning is displayed is that the first excerpt is not proper C - it has a constraint violation that a standards-compliant C compiler must produce a diagnostisc message for. It violates the C11 6.7.2.1p2:
Constraints
A struct-declaration that does not declare an anonymous structure or anonymous union shall contain a struct-declarator-list.
Meaning that it is OK to write
struct foo {
struct {
int a;
};
};
since the inner struct declares an anonymous structure, i.e. it is not named.
But in your example the struct address has a name - address - and therefore it must have a declarator list after the closing brace - declarator list being for example a1 as in your example, or more complex foo, *bar, **baz[23][45].
The syntax of a structure definition is:
struct identifier {
type member_name;
// ...
};
If you add an identifier just after the closing curly brace, you're declaring a variable with that defined struct.
In your first example the compiler consider the address struct as member type. it's like if you writes:
struct identifier {
type ; // No member name is specified
type a1;
// ...
}
But in the second example you specified the member name:
struct identifier {
type a1; // Member name specified
// ...
}
And here is an example of the warning: http://ideone.com/KrnYiE.
Going to also throw this out there that this error may also show up if you don't properly forward declare types found in other namespaces.
https://stackoverflow.com/a/19001722/1330381
Example
namespace A {
// forward declarations
namespace X {
namespace Y {
class MyType;
}
}
namespace B {
class Foo() {
void methodBar(const X::Y::MyType& mt);
}
}
In my case, i had the same warning because the structure name was previously used and changing the structure name solved the problem.
error: invalid type argument of unary '*' (have 'int')
struct test_t {
int var1[5];
int var2[10];
int var3[15];
}
test_t* test;
test->var1[0] = 5;
How can I solve this problem?
You should write:
struct test_t* test;
Or use typedef if you want to avoid writing struct every time you declare a variable of that type:
typedef struct test_t {
int var1[5];
int var2[10];
int var3[15];
} test_t;
test_t* test;
Side note: In C++ the struct name is placed in the regular namespace, therefore there is no need to write struct before declaring a variable of that type.
When you declare a structure variable, struct keyword should be there like
struct test_t* test;
If you don't want to use struct keyword every time you declare a variable, simply use typedef.