Struct definition Function of type Static - c

I came across the below line in one of the code:
static DATA_BLOCK_SOX_s data_blockSox = {.header.uniqueId = DATA_BLOCK_ID_SOX};
I want to know what form of Syntax is this and what is exactly happening here
Thanks

That's a C struct initializer with named fields (designated initializers).
static DATA_BLOCK_SOX_s data_blockSox = {.header.uniqueId = DATA_BLOCK_ID_SOX};
Creates a DATA_BLOCK_SOX_s in load-time allocated storage called data_blockSox scoped to this file, initializing all fields to binary zero except for header.uniqueId (where header is clearly a nested struct or union) which is initialized to DATA_BLOCK_ID_SOX.
I have used indentation to infer file scope. That could be incorrect. If it's inside a function it should be indented, but as we know, the compiler doesn't care.
In the unlikely case that you actually care about systems for which NULL is not binary zero, it has been pointed out that pointer fields should be initialized to NULL even on systems that have NULL as not binary zero. I have only ever seen that spec not followed.

This looks like C99. And should be something like:
struct Point {int x, y;}; // This would be the stand-in for DATA_BLOCK_SOX_s
typedef struct Point Point;
static Point point = { .y = 10, .x = 5 }; // here the members y and x get their values
In your case there is a nested struct called header. This as a member calles uniqueId.

Related

Usb device id table understanding

I am trying to understand different ways linux kernel initialize structures. In this query I wrote a sample usb driver but I do not understand some points, pointed as comments preceding ??
static struct usb_device_id pen_table[] = //?? why pen_table is an array
{
{ USB_DEVICE(0xaaaa , 0x8816) }, //??what type of array initialization is this
{} /* Terminating entry */ //??how this terminates
};
I tried to initialize device id table in this way, but I am getting errors as near initialization
static struct usb_device_id pen_table = {
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor=0xaaaa,
.idProduct = 0x8816,
};
You should have Linux kernel source at hand to really understand this.
Why pen_table is an array?
It wil be necessary in MODULE_DEVICE_TABLE (see Hard time in understanding MODULE_DEVICE_TABLE(usb, id_table) usage) and in defining instance of usb_driver struct, see http://opensourceforu.efytimes.com/2011/11/usb-drivers-in-linux-2/.
what type of array initialization is this?
USB_DEVICE is a macro defined in include/linux/usb.h:
#define USB_DEVICE(vend, prod) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
.idVendor = (vend), \
.idProduct = (prod)
how this terminates?
C standard says:
The initialization shall occur in initializer list order, each
initializer provided for a particular subobject overriding any
previously listed initializer for the same subobject; all subobjects
that are not initialized explicitly shall be initialized implicitly
the same as objects that have static storage duration.
and:
If an object that has automatic storage duration is not initialized
explicitly, its value is indeterminate. If an object that has static
storage duration is not initialized explicitly, then:
if it has pointer type, it is initialized to a null pointer;
if it has arithmetic type, it is initialized to (positive or
unsigned) zero;
if it is an aggregate, every member is initialized (recursively)
according to these rules;
if it is a union, the first named member is initialized
(recursively) according to these rules.
Thanks to this, id_table is defined as a pointer and not as an array inside usb_driver:
const struct usb_device_id *id_table;
Instead of passing an array size independently a function that uses id_table will increment pointer to id_table until one of its elements is NULL. See this short example that represents this technique:
#include <stdio.h>
#include <stdlib.h>
struct small
{
int a;
int b;
};
struct big
{
struct small *s;
};
struct small table[] =
{
{1, 1},
{2, 2},
{3, 3},
{}
};
int main(void)
{
struct big b = {
.s = table
};
const struct small *s;
/* traverse through table using pointer arithmetic */
for (s = b.s; s->a; s++)
{
printf("%d\n", s->a);
printf("%d\n", s->b);
}
exit(0);
}
I tried to initialize device id table in this way, but I am getting
errors as near initialization
I don't, are you sure you're not trying to redefine pen_table? What's an error message?
It's an array because it's how the data structure is defined and used.
You have n number of entries, and then a terminating entry (in this case, all zeros).
Wherever this array is used in initialization, it will start at the table symbol and consume entries until it hits the terminator, then stop. This way you don't need to communicate the number of entries as well.
This pattern facilitates late binding of configuration data with the library, and allows more compile time configuration, rather than run time configuration, and also requires fewer things to be in sync to operate correctly (so less chance for error).
Your second struct doesn't have a terminator, so the thing that's parsing the table just keeps on going and going and going until it crashes or gets errors.

Are struct names pointers to first element?

I found a few similar questions but none of them helped much. Are struct names pointers to the first element of the struct, similar to an array?
struct example {
int foo;
int bar;
};
struct example e;
e.foo = 5;
e.bar = 10;
printf("%d\n%d\n%d\n%d\n%d\n%d\n", e, e.foo, e.bar, &e, &e.foo, &e.bar);
Output:
5
5
10
2033501712
2033501712
2033501716
All of the answers to the other questions said "no", but this output confuses me. All help would be greatly appreciated.
The address of a struct is indeed the address of the first element, though you'll need to know the type of the element in order to safely cast it.
(C17 ยง6.7.2.1.15: "A pointer to a structure object, suitably
converted, points to its initial member ... and vice versa. There may
be unnamed padding within as structure object, but not at its
beginning.")
While it's kind of ugly, numerous pieces of production software rely on this. QNX, for example, uses this kind of behavior in open control block (OCB) logic when writing resource managers. Gtk also something similar.
Your current implementation is dangerous though. If you must rely on this behavior, do it like so, and don't attempt to pass a pointer-to-struct as an argument to printf(), as you're intentionally breaking a feature of a language with minimal type-safety.
struct example {
int foo;
int bar;
};
struct example myStruct = { 1, 2 };
int* pFoo = (int*)&myStruct;
printf("%d", *pFoo);
Finally, this only holds for the first element. Subsequent elements may not be situation where you expect them to be, namely due to struct packing and padding.
struct names aren't pointers to anything. You are invoking undefined behaviour by passing a struct to printf with an incompatible format specifier %d. It may seem to "work" because the first member of the struct has the same address as the struct itself.

Understanding concept of structs

I want to know what is the difference between
int a;
and
struct node{
int a;
};
struct node b;
Are they the same?
No they are not same. Operations permitted by language on a and b are different as their types are different. When they contain same bit patterns, interpretation of those bit patterns may be different.
Compiler may take different path to return an int vs struct node from a function or while passing them as function argument.
Essentially a and b.a possess same behavior. Compiler may sometime choose to optimize single member structs with the type of member.
Differences
1. Compile time: Type of a and type of b are different
2. Compile time: a = 42 (OK), b = 42 (Error)
3. Run time: Compiler may choose to use different strategies while copying a and b to a different variable of same type.
4. section 6.7.2.1 in the C99 standard says There may be unnamed padding within a structure object, but not at its beginning., which means sizeof a is allowed to be not equal to the sizeof b
Extra notesSingle member structs are almost always not required except in cases when
1. Other members are conditionally compiled out. (To keep the code manageable)
2. When you plan to pass an array as function parameter, return an array from a function or copy array using assignation operator.
3. Restrict operations. [For example you don't want emp id to be added, subtracted etc but assignation is OK]
No, they are not same.
int a; --> a variable named a of type integer.
struct node b; --> a variable named b of type struct node.
here, the struct contains only int a but that's not the case always. These two variables are
indeed of different data types.
representations are different.
access methods are different.
As per your example both are same. But structure is mainly used for accessing the more than one variable using the common variable name.
struct node {
int a;
float b;
char c;
};
struct node b;
So now using the variable b we can access the three different data types. So this is the main advantage of structure.
Accessing the structure as normal variable. b.a;
If you are using the pointer then this will be b->a. Note you have to allocate the memory for that.

typedef stuct with forward declaration in C

I have something like:
typedef struct Data DATA, *DATA_PTR;
typedef struct Units UNITS, *UNITS_PTR;
struct Data
{
double miscData;
UNITS units;
};
struct Units
{
double x[2];
double y[2];
double z[2];
};
in my project_typedef.h file.
In another file, I have something like:
void fileInput(DATA_PTR data)
{
//usual declarations and other things
data->miscData = 0; //Works!
data->units.x[0] = 5; //Doesn't work
//etc...
}
However, this doesn't work since units is declared after data in project_typedef.h (if I switch the order it works). The error that i get is "left of '.x' must have struct/union type". I thought that the forward declaration would fix this issue. Why not?
When you define Data, all members must be complete types. Since UNITS isn't a complete type at that point, this doesn't work. (By contrast, UNITS_PTR would be fine, since pointers to incomplete types are complete types.)
Simply put the Units definition above the Data definition and you should be fine.
(As #cnicutar already noted, you're also using the array x wrong.)
The forward declaration allows you to use its name in context where an incomplete type is allowed. Declaring a struct member is not one of such cases, the complete definition must be known as it contributes to the struct layout.
for a struct definition you should always use complete types for all members in a structure... but this is not the case with UNITS units in struct Data,which declares a variable named units of type struct Units which is never declared before the struct Data... this reflects an error.. you should place the Units definition above Data definition.. and all will work fine..
and regarding forward declaration this does not work since whenever a struct variable is defined, the compiler first allocates the memory required to the struct (struct members donot have a memory allocated to them, unless they are linked to a struct type of variable.. thats why struct variables cant be initialized inside struct template).. :)
There is no prototype for struct. This is because compiler needs to know size of struct before using it. You could use pointer on struct, because pointers have known size no matter which type they point to.

How is it legal to reference an undefined type inside a structure?

As part of answering another question, I came across a piece of code like this, which gcc compiles without complaint.
typedef struct {
struct xyz *z;
} xyz;
int main (void) {
return 0;
}
This is the means I've always used to construct types that point to themselves (e.g., linked lists) but I've always thought you had to name the struct so you could use self-reference. In other words, you couldn't use xyz *z within the structure because the typedef is not yet complete at that point.
But this particular sample does not name the structure and it still compiles. I thought originally there was some black magic going on in the compiler that automatically translated the above code because the structure and typedef names were the same.
But this little beauty works as well:
typedef struct {
struct NOTHING_LIKE_xyz *z;
} xyz;
What am I missing here? This seems a clear violation since there is no struct NOTHING_LIKE_xyz type defined anywhere.
When I change it from a pointer to an actual type, I get the expected error:
typedef struct {
struct NOTHING_LIKE_xyz z;
} xyz;
qqq.c:2: error: field `z' has incomplete type
Also, when I remove the struct, I get an error (parse error before "NOTHING ...).
Is this allowed in ISO C?
Update: A struct NOSUCHTYPE *variable; also compiles so it's not just inside structures where it seems to be valid. I can't find anything in the c99 standard that allows this leniency for structure pointers.
As the warning says in the second case, struct NOTHING_LIKE_xyz is an incomplete type, like void or arrays of unknown size. An incomplete type can only appear in a struct as a type pointed to (C17 6.7.2.1:3), with an exception for arrays of unknown size that are allowed as the last member of a struct, making the struct itself an incomplete type in this case. The code that follows cannot dereference any pointer to an incomplete type (for good reason).
Incomplete types can offer some datatype encapsulation of sorts in C...
The corresponding paragraph in http://www.ibm.com/developerworks/library/pa-ctypes1/ seems like a good explanation.
The parts of the C99 standard you are after are 6.7.2.3, paragraph 7:
If a type specifier of the form
struct-or-union identifier occurs
other than as part of one of the above
forms, and no other declaration of the
identifier as a tag is visible, then
it declares an incomplete structure or
union type, and declares the
identifier as the tag of that type.
...and 6.2.5 paragraph 22:
A structure or union type of unknown
content (as described in 6.7.2.3) is
an incomplete type. It is completed,
for all declarations of that type, by
declaring the same structure or union
tag with its defining content later in
the same scope.
The 1st and 2nd cases are well-defined, because the size and alignment of a pointer is known. The C compiler only needs the size and alignment info to define a struct.
The 3rd case is invalid because the size of that actual struct is unknown.
But beware that for the 1st case to be logical, you need to give a name to the struct:
// vvv
typedef struct xyz {
struct xyz *z;
} xyz;
otherwise the outer struct and the *z will be considered two different structs.
The 2nd case has a popular use case known as "opaque pointer" (pimpl). For example, you could define a wrapper struct as
typedef struct {
struct X_impl* impl;
} X;
// usually just: typedef struct X_impl* X;
int baz(X x);
in the header, and then in one of the .c,
#include "header.h"
struct X_impl {
int foo;
int bar[123];
...
};
int baz(X x) {
return x.impl->foo;
}
the advantage is out of that .c, you cannot mess with the internals of the object. It is a kind of encapsulation.
You do have to name it. In this:
typedef struct {
struct xyz *z;
} xyz;
will not be able to point to itself as z refers to some complete other type, not to the unnamed struct you just defined. Try this:
int main()
{
xyz me1;
xyz me2;
me1.z = &me2; // this will not compile
}
You'll get an error about incompatible types.
Well... All I can say is that your previous assumption was incorrect. Every time you use a struct X construct (by itself, or as a part of larger declaration), it is interpreted as a declaration of a struct type with a struct tag X. It could be a re-declaration of a previously declared struct type. Or, it can be a very first declaration of a new struct type. The new tag is declared in scope in which it appears. In your specific example it happens to be a file scope (since C language has no "class scope", as it would be in C++).
The more interesting example of this behavior is when the declaration appears in function prototype:
void foo(struct X *p); // assuming `struct X` has not been declared before
In this case the new struct X declaration has function-prototype scope, which ends at the end of the prototype. If you declare a file-scope struct X later
struct X;
and try to pass a pointer of struct X type to the above function, the compiler will give you a diagnostics about non-matching pointer type
struct X *p = 0;
foo(p); // different pointer types for argument and parameter
This also immediately means that in the following declarations
void foo(struct X *p);
void bar(struct X *p);
void baz(struct X *p);
each struct X declaration is a declaration of a different type, each local to its own function prototype scope.
But if you pre-declare struct X as in
struct X;
void foo(struct X *p);
void bar(struct X *p);
void baz(struct X *p);
all struct X references in all function prototype will refer to the same previosly declared struct X type.
I was wondering about this too. Turns out that the struct NOTHING_LIKE_xyz * z is forward declaring struct NOTHING_LIKE_xyz. As a convoluted example,
typedef struct {
struct foo * bar;
int j;
} foo;
struct foo {
int i;
};
void foobar(foo * f)
{
f->bar->i;
f->bar->j;
}
Here f->bar refers to the type struct foo, not typedef struct { ... } foo. The first line will compile fine, but the second will give an error. Not much use for a linked list implementation then.
When a variable or field of a structure type is declared, the compiler has to allocate enough bytes to hold that structure. Since the structure may require one byte, or it may require thousands, there's no way for the compiler to know how much space it needs to allocate. Some languages use multi-pass compilers which would be able find out the size of the structure on one pass and allocate the space for it on a later pass; since C was designed to allow for single-pass compilation, however, that isn't possible. Thus, C forbids the declaration of variables or fields of incomplete structure types.
On the other hand, when a variable or field of a pointer-to-structure type is declared, the compiler has to allocate enough bytes to hold a pointer to the structure. Regardless of whether the structure takes one byte or a million, the pointer will always require the same amount of space. Effectively, the compiler can tread the pointer to the incomplete type as a void* until it gets more information about its type, and then treat it as a pointer to the appropriate type once it finds out more about it. The incomplete-type pointer isn't quite analogous to void*, in that one can do things with void* that one can't do with incomplete types (e.g. if p1 is a pointer to struct s1, and p2 is a pointer to struct s2, one cannot assign p1 to p2) but one can't do anything with a pointer to an incomplete type that one could not do to void*. Basically, from the compiler's perspective, a pointer to an incomplete type is a pointer-sized blob of bytes. It can be copied to or from other similar pointer-sized blobs of bytes, but that's it. the compiler can generate code to do that without having to know what anything else is going to do with the pointer-sized blobs of bytes.

Resources