The use of a pointer to an unnamed struct in C? - c

What's the use for something like
typedef struct
{
int field_1;
float field_2;
}*T;
in C ?
Since a struct is a datatype in C, where the information about the datatype pointed by T is stored and how to correctly initialize a variable var that is declared as T var ?

T is an alias for a pointer to the structure. The structure itself is not a type, but T is.
T is not stored anywhere but in the compilers internal tables for types.
You can use it like
T myVariable = malloc(sizeof(*myVariable));

I would expect something like that (pointer-to-unnamed-struct) to be used in order to describe the data which are coming from outside of the program in question (e.g. given as a return value from a library function, when it is allocated and deallocated by that library). Then such typedef is just a specification how to access these data.

The use is as if the struct was named. I.e. you can access struct fields via this pointer. For example:
void fun(T p) {
if (p->field_1 == 0) p->field_2 = 1.2345;
}
If you never need to reference a structure itself by a name, there is no need to give it one. The info about structure (and its members) is stored in compiler tables in the same way as for named structures.
This construct is useful in defining complex data structures (possibly with unions) and not to pollute global name space with useless names. For example:
struct myUsefulStructure {
int stype;
union {
struct { // a structure which is never referenced itself
...
} x;
struct { // another structure which is never referenced itself
...
} y;
} u;
};

Related

Getting information (types, values...etc) on members of C type struct

I would like to get some help on C-style struct. I do not have much understanding in C so I am not familiar with the basics.
Right now, I have a struct (outerStruct) that has other structs as members (innerStruct1, innerStruct2...). What I need to do is to get values of MEMBER VARIABLES OF innerStruct1, innerStruct2....
The only information I have is the pointer to outerStruct and a data structure that has all the possible variable types of MEMBER VARIABLES OF EACH innerStructs. Note that all the variable names are just variable type
+ "_val" so if I can types of member variables, I will be able to get variable names as well.
I need to get the information on the MEMBERS OF the innerStructs and parse them into a text file, s.t variable name and variable value would show up.
Can I get the member variable of the innerStruct without using variable names? Since C plays with the memory allocation, maybe this is possible? If this is not possible, what are possible information that I can get?
The container of variable names and types is quite large so if I use all values to retrieve information, it will do too many null checks, and the time will be linear to the size of the container. Instead, I would like to know if I can take advantage of the naming convention and make the code more efficient.
struct outerStruct {
innerStruct1 innerStruct1_val;
innerStruct2 innerStruct2_val;
}
struct innerStruct1 {
int int_val = 5;
char char_val = 'a';
}
struct innerStruct2 {
float float_val = 4.0;
double double_val = 5.0;
}
Expected output(print to screen):
"innerStruct1_val : int_val = 5, char_val = 'a' || innerStruct2_val : float_val = 4.0, double_val = 5.0"
TL;DR I want to get values of the inner struct from a nested struct without using the actual variable names.
(Also, the code is here to only show the lay out of the structure. Correct syntax will be used.)
In C, you have to manually walk the members of respective structures. But, even if you want to keep the structure internals "private", by only making the structure tag name public, you can provide a public function to print the function.
struct outerStruct;
void print_outerStruct(const struct outerStruct *);
Likewise for the innter structures.
Since you have to define the complete outer structure someplace for it to be useful, that place would also be the place to provide the implementation of its print function.
struct outerStruct {
struct innerStruct1 innerStruct1_val;
struct innerStruct2 innerStruct2_val;
};
void print_outerStruct (const struct outerStruct *os) {
printf("outerStruct (%p) { ", os);
printf("%s: ", "innerStruct1_val");
print_innerStruct1(&os->innerStruct1_val);
printf("%s: ", "innerStruct2_val");
print_innerStruct2(&os->innerStruct2_val);
printf(" }\n");
}
With sufficient scaffolding, you may be able to generate these print functions mechanically. For example, it might require writing a parser for your structures.

Initializing a const array inside a struct

#define LENGTH 6
typedef char data_t[LENGTH];
struct foo {
const data_t data;
...
}
...
void bar(data_t data) {
printf("%.6s\n", data);
struct foo myfoo = {*data};
printf("%.6s\n", foo.data);
}
I'm trying to have this struct which holds directly the data I'm interested in, sizeof(foo) == 6+the rest, not sizeof(foo) == sizeof(void*)+the rest. However I can't find a way to initialize a struct of type foo with a data_t. I think maybe I could remove the const modifier from the field and use memcpy but I like the extra safety and clarity.
I don't get any compile errors but when I run the code I get
123456
1??
so the copy didn't work properly I think.
This is for an arduino (or similar device) so I'm trying to keep it to very portable code.
Is it just not possible ?
EDIT: removing the const modifier on the data_t field doesn't seem to help.
It is possible to do this, for some cost >=0.
typedef struct
{
char c[LENGTH];
} data_t; // this struct is freely copyable
struct foo
{
const data_t data; // but this data member is not
int what;
};
void foo (char* x) {
data_t d; // declare freely copyable struct instance
memcpy(d.c, x, sizeof(d.c)); // memcpy it
struct foo foo = { d, 42 }; // initialise struct instance with const member
...
};
Some compilers (e.g. clang) are even able to optimise away the redundant copying (from x to d.c and then from d to foo.data ⇒ from x straight to foo.data). Others (gcc I'm looking at you) don't seem to be able to achieve this.
If you pass around pointers to data_t rather than straight char pointers, you won't need this additional memcpy step. OTOH in order to access the char array inside foo you need another level of member access (.data.c instead of just .data; this has no runtime cost though).
It's impossible to do it in a standard compliant way.
Due to its being const, const char data[6]; must be initialized to be usable, and it may only be initialized statically (static objects with no initializer get automatically zeroed), with a string literal, or with a brace-enclosed initializer list. You cannot initialize it with a pointer or another array.
If I were you, I would get rid of the const, document that .data shouldn't be changed post-initialization, and then use memcpy to initialize it.
(const on struct members doesn't work very well in my opinion. It effectively prevents you from being able to have initializer functions, and while C++ gets around the problem a little bit by having special language support for its constructor functions, the problem still remains if the const members are arrays).

Why are named nested structure allowed?

I stumbled upon a very strange feature of C: you can declare a named structure inside another structure provided that declare a member variable of that type at the same time:
struct Robot_st {
int pos_x;
int pos_y;
struct BatteryStatus_st { /* <- named struct */
int capacity;
int load;
} battery;
};
The inner structure becomes then available outside the structure as any other type, rendering strange code like this perfectly valid:
struct Robot_st my_robot = {2, 3, {200, 50}};
struct BatteryStatus_st battery_snapshot; /* <- use of inner struct */
memcpy(
&battery_snapshot,
&my_robot.battery,
sizeof(struct BatteryStatus_st)
);
printf("robot position: %d,%d\n", my_robot.pos_x, my_robot.pos_y);
printf("battery load: %d%%\n", battery_snapshot.load);
Nesting unnamed structures feels right, because as you cannot access the type later, there is no confusion about the scope of the type. The above code is also not valid in C++, although the nested declaration is, because C++ understands it as a type in the namespace of the outer structure, so you need to access it using
struct Robot_st::BatteryStatus_st battery_snapshot;
which, despite feeling strange to declare both a type and a member at the same time, makes more sense.
So why is this construct valid in C? Is there any history/reason behind? Is there a use case for such a construct? (Mine was a mistake that led to failures, thus the question.)
Link to full working code.
Such constructs were allowed in C originally because structure names occupied a universe all their own which never had any sort of scoping rules applied to it [struct member names did too, by the way, which is why some of the structure types in older standard libraries have prefixes on their members]. Because some code exists which uses structure names in a fashion inconsistent with scoping, the standard could not be changed to prohibit such usage without breaking existing code. While there are times when it's worthwhile to break existing code (e.g. to rid C of the abomination called gets) this really isn't one of them.
In addition to the other two answers, here is a real usecase that calls for such a named inner struct:
struct LinkedList {
//data members stored once per list
struct LinkedListNode {
//data members for each entry of the list
struct LinkedListNode *next;
} *head, *tail;
};
Its hard to write a more concise definition for the structure of a linked list.
An unnamed inner struct won't do: The code that inserts something into the linked list will likely have to declare local variables with node pointers. And there is no point in declaring the node structure outside of the linked list structure.
Well, this is legal in C:
struct BatteryStatus_st {
int capacity;
int load;
};
struct Robot_st {
int pos_x;
int pos_y;
struct BatteryStatus_st battery;
};
and, as you pointed out, it is effectively identical to the code you posted (since C doesn't have the namespace/scoping rules introduced in C++).
If moving the "inner" type inside doesn't change anything, but may sometimes clarify intent, it would seem odd to prohibit it.
Let's say I have this structure:
struct OuterStruct
{
int a;
struct InnerStruct
{
int i;
int j;
} b;
} s;
Now I can access s.a, and I can even save it in a variable, to better handle it, pass it to functions, ...
int sa = s.a;
Well, now I want to do the same with s.b, and to do so I need InnerStruct to have a name!
???? sb = s.b; // here I have to use InnerStruct, otherwise sb would have no valid type!
The alternative would be to declare InnerStruct outside of OuterStruct, and then putting an instance of it inside as member of OuterStruct. But this would hide the fact that InnerStruct belongs to OuterStruct, making your intent less clear.

How can I hide the declaration of a struct in C?

In the question Why should we typedef a struct so often in C?, unwind answered that:
In this latter case, you cannot return
the Point by value, since its
declaration is hidden from users of
the header file. This is a technique
used widely in GTK+, for instance.
How is declaration hiding accomplished? Why can't I return the Point by value?
ADD:
I understood why I can't return the struct by value, but, is still hard to see why i can't deference this point in my function. i.e. If my struct have member named y, why i can't do it?
pointer_to_struct->y = some_value;
Why should I use methods to do it? (Like Gtk+)
Thanks guys, and sorry for my bad english again.
Have a look at this example of a library, using a public header file, a private header file and an implementation file.
In file public.h:
struct Point;
struct Point* getSomePoint();
In file private.h:
struct Point
{
int x;
int y;
}
In file private.c:
struct Point* getSomePoint()
{
/* ... */
}
If you compile these three files into a library, you only give public.h and the library object file to the consumer of the library.
getSomePoint has to return a pointer to Point, because public.h does not define the size of Point, only that is a struct and that it exists. Consumers of the library can use pointers to Point, but can not access the members or copy it around, because they do not know the size of the structure.
Regarding your further question:
You can not dereference because the program using the library does only have the information from private.h, that does not contain the member declarations. It therefore can not access the members of the point structure.
You can see this as the encapsulation feature of C, just like you would declare the data members of a C++ class as private.
What he means is that you cannot return the struct by-value in the header, because for that, the struct must be completely declared. But that happens in the C file (the declaration that makes X a complete type is "hidden" in the C file, and not exposed into the header), in his example. The following declares only an incomplete type, if that's the first declaration of the struct
struct X;
Then, you can declare the function
struct X f(void);
But you cannot define the function, because you cannot create a variable of that type, and much less so return it (its size is not known).
struct X f(void) { // <- error here
// ...
}
The error happens because "x" is still incomplete. Now, if you only include the header with the incomplete declaration in it, then you cannot call that function, because the expression of the function call would yield an incomplete type, which is forbidden to happen.
If you were to provide a declaration of the complete type struct X in between, it would be valid
struct X;
struct X f(void);
// ...
struct X { int data; };
struct X f(void) { // valid now: struct X is a complete type
// ...
}
This would apply to the way using typedef too: They both name the same, (possibly incomplete) type. One time using an ordinary identifier X, and another time using a tag struct X.
In the header file:
typedef struct _point * Point;
After the compiler sees this it knows:
There is a struct called _point.
There is a pointer type Point that can refer to a struct _point.
The compiler does not know:
What the struct _point looks like.
What members struct _point contains.
How big struct _point is.
Not only does the compiler not know it - we as programmers don't know it either. This means we can't write code that depends on those properties of struct _point, which means that our code may be more portable.
Given the above code, you can write functions like:
Point f() {
....
}
because Point is a pointer and struct pointers are all the same size and the compiler doesn't need to know anything else about them. But you can't write a function that returns by value:
struct _point f() {
....
}
because the compiler does not know anything about struct _point, specifically its size, which it needs in order to construct the return value.
Thus, we can only refer to struct _point via the Point type, which is really a pointer. This is why Standard C has types like FILE, which can only be accessed via a pointer - you can't create a FILE structure instance in your code.
Old question, better answer:
In Header File:
typedef struct _Point Point;
In C File:
struct _Point
{
int X;
int Y;
};
What that post means is: If you see the header
typedef struct _Point Point;
Point * point_new(int x, int y);
then you don't know the implementation details of Point.
As an alternative to using opaque pointers (as others have mentioned), you can instead return an opaque bag of bytes if you want to avoid using heap memory:
// In public.h:
struct Point
{
uint8_t data[SIZEOF_POINT]; // make sure this size is correct!
};
void MakePoint(struct Point *p);
// In private.h:
struct Point
{
int x, y, z;
};
void MakePoint(struct Point *p);
// In private.c:
void MakePoint(struct Point *p)
{
p->x = 1;
p->y = 2;
p->z = 3;
}
Then, you can create instances of the struct on the stack in client code, but the client doesn't know what's in it -- all it knows is that it's a blob of bytes with a given size. Of course, it can still access the data if it can guess the offsets and data types of the members, but then again you have the same problem with opaque pointers (though clients don't know the object size in that case).
For example, the various structs used in the pthreads library use structs of opaque bytes for types like pthread_t, pthread_cond_t, etc. -- you can still create instances of those on the stack (and you usually do), but you have no idea what's in them. Just take a peek into your /usr/include/pthreads.h and the various files it includes.

Why can't we initialize members inside a structure?

Why can't we initialize members inside a structure ?
example:
struct s {
int i = 10;
};
If you want to initialize non-static members in struct declaration:
In C++ (not C), structs are almost synonymous to classes and can have members initialized in the constructor.
struct s {
int i;
s(): i(10)
{
}
};
If you want to initialize an instance:
In C or C++:
struct s {
int i;
};
...
struct s s_instance = { 10 };
C99 also has a feature called designated initializers:
struct s {
int i;
};
...
struct s s_instance = {
.i = 10,
};
There is also a GNU C extension which is very similar to C99 designated initializers, but it's better to use something more portable:
struct s s_instance = {
i: 10,
};
The direct answer is because the structure definition declares a type and not a variable that can be initialized. Your example is:
struct s { int i=10; };
This does not declare any variable - it defines a type. To declare a variable, you would add a name between the } and the ;, and then you would initialize it afterwards:
struct s { int i; } t = { 10 };
As Checkers noted, in C99, you can also use designated initializers (which is a wonderful improvement -- one day, C will catch up with the other features that Fortran 66 had for data initialization, primarily repeating initializers a specifiable number of times). With this simple structure, there is no benefit. If you have a structure with, say, 20 members and only needed to initialize one of them (say because you have a flag that indicates that the rest of the structure is, or is not, initialized), it is more useful:
struct s { int i; } t = { .i = 10 };
This notation can also be used to initialize unions, to choose which element of the union is initialized.
Note that in C++ 11, the following declaration is now allowed:
struct s {
int i = 10;
};
This is an old question, but it ranks high in Google and might as well be clarified.
Edit2: This answer was written in 2008 and relates to C++98. The rules for member initialization have changed in subsequent versions of the language.
Edit: The question was originally tagged c++ but the poster said it's regarding c so I re-tagged the question, I'm leaving the answer though...
In C++ a struct is just a class which defaults for public rather than private for members and inheritance.
C++ only allows static const integral members to be initialized inline, other members must be initialized in the constructor, or if the struct is a POD in an initialization list (when declaring the variable).
struct bad {
static int answer = 42; // Error! not const
const char* question = "what is life?"; // Error! not const or integral
};
struct good {
static const int answer = 42; // OK
const char* question;
good()
: question("what is life?") // initialization list
{ }
};
struct pod { // plain old data
int answer;
const char* question;
};
pod p = { 42, "what is life?" };
We can't initialize because when we declared any structure than actually what we do, just inform compiler about their presence i.e no memory allocated for that and if we initialize member with no memory for that. Normally what happens when we initialize any variable that depends on the place where we declared variable compiler allocate memory for that variable.
int a = 10;
if it's auto than in stack memory going to allocate
if it's global than in data sections memory going to allocate
So what memory is required to hold that data but in case of structure no memory is there so not possible to initialize it.
As you said it's just a member not a variable. When you declare a variable the compiler will also provide memory space for those variables where you can put values. In the case a of a struct member the compiler is not giving memory space for it, so you cannot assign values to struct members unless you create a variable of that struct type.

Resources