C structure syntax - c

C header sample.
typedef LPVOID UKWD_USB_DEVICE;
typedef struct _UKWD_USB_DEVICE_INFO {
DWORD dwCount;
unsigned char Bus;
unsigned char Address;
unsigned long SessionId;
USB_DEVICE_DESCRIPTOR Descriptor;
} UKWD_USB_DEVICE_INFO, *PUKWD_USB_DEVICE_INFO, * LPUKWD_USB_DEVICE_INFO;
My Understanding
struct defines a structure (the part between {}). The structure's type is _UKWD_USB_DEVICE_INFO. After the closing } UKWD_USB_DEVICE_INFO is an alias to this structure.
Question
What is the purpose of the declarations after that. * PUKD_USB_DEVICE_INFO and *LPUKWD_USB_DEVICE_INFO. Do these pointer aliases mean something different if one is touching the variable and the other has a space between the * and lettering?

C typedef declarations are understood by analogy with variable declarations.
int a, *b;
declares the values a of type int and b of type int*.
typedef int A, *B;
declares the type A equivalent to int and the type B equivalent to int*. So, just think about what the variable type would be if this was a variable declaration.
So yes, PUKWD_USB_DEVICE_INFO becomes equivalent to struct _UKWD_USB_DEVICE_INFO*.
EDIT
Also, the space does not matter. C is a whitespace language. The extra aliases are not necessary, they are just there to fit with conventions of various projects and APIs that like to call pointer types by names that include P or other substrings. Sometimes these projects end up with multiple conventions over time, so there are multiple aliases. They can also be needed for compatibility reasons when APIs get updated, or between different platforms.

Are these pointer aliases?
Yes.
Does it mean anything if one is touching the variable and the other has a space between the * and lettering?
No. In C, spaces between tokens have no meaning to the compiler. They merely change the readability for people looking at the code.
I have seen very few code examples online use more than one name after the close of the curly brackets. Any insight on this?
Typically, and in this case in particular, it's done to allow symbol names that may represent different types, but also may not.
You're seeing that on your architecture, a P "pointer" and a LP "long pointer" happen to be the same type.
On a 16-bit architecture, you would be looking at a different header and those types would be different.

This style of definition is common on the Windows platform. In the days of 16 bit segmented architectures, each structure definition typedef had also 2 pointer typedefs for near and far (aka long pointers):
typedef LPVOID UKWD_USB_DEVICE;
typedef struct _UKWD_USB_DEVICE_INFO {
DWORD dwCount;
unsigned char Bus;
unsigned char Address;
unsigned long SessionId;
USB_DEVICE_DESCRIPTOR Descriptor;
} UKWD_USB_DEVICE_INFO, NEAR * PUKWD_USB_DEVICE_INFO, FAR * LPUKWD_USB_DEVICE_INFO;
NEAR pointers were 16 bit wide and FAR pointers were 32 bit wide. Most Windows APIs took FAR pointers, and their prototypes used the pointer typedefs. Incidentally, LPVOID was defined this way:
typedef void FAR *LPVOID;
32 bit Windows came out in 1995 and made this obsolete. NEAR and FAR keywords were kept for a while, defined as empty, for compatibility reasons.
Compatibility with 16 bit Windows has long become useless, but the usage still lingers as the typedefs are still in use, but the FAR and NEAR keywords were removed.
The space between * and PUKWD_USB_DEVICE_INFO is ignored, but I agree with you it is rather confusing to put one there.

Yes, it's a pointer alias, you can then use PUKWD_USB_DEVICE_INFO as UKWD_USB_DEVICE_INFO*. Most Windows structs do this:
That L in the third alias stands for long (pointer), and unless I'm much mistaken, it has no meaning in 32/64 bit code - it's likely a leftover from 16 bit stuff, as is the case with that WNDCLASS definition.

Related

Work on an array of signed int as if it contained unsigned values

I've inherited some old code that assumes that an int can store values from -231 to 2^31-1, that overflow just wraps around, and that the sign bit is the high-order bit. In other words, that code should have used uint32_t, except that it wasn't. I would like to fix this code to use uint32_t.
The difficulty is that the code is distributed as source code and I'm not allowed to change the external interface. I have a function that works on an array of int. What it does internally is its own business, but int is exposed in the interface. In a nutshell, the interface is:
struct data {
int a[10];
};
void frobnicate(struct data *param);
I'd like to change int a[10] to uint32_t a[10], but I'm not allowed to modify the definition of struct data.
I can make the code work on uint32_t or unsigned internally:
struct internal_data {
unsigned a[10];
};
void frobnicate(struct data *param) {
struct internal_data *internal = (struct internal_data *)param;
// ... work with internal ...
}
However this is not actually correct C since it's casting between pointers to different types.
Is there a way I can add compile-time guards so that, for the rare people for whom int isn't “old-school” 32-bit, the code doesn't build? If int is less than 32 bits, the code has never worked anyway. For the vast majority of users, the code should build, and in a way that tells the compiler not to do “weird” things with overflowing int calculations.
I distribute the source code and people may use it with whatever compiler they choose, so compiler-specific tricks are not relevant.
I'm at least going to add
#if INT_MIN + 1 != -0x7fffffff
#error "This code only works with 32-bit two's complement int"
#endif
With this guard, what can go wrong with the cast above? Is there a reliable way of manipulating the int array as if its elements were unsigned, without copying the array?
In summary:
I can't change the function prototype. It references an array of int.
The code should manipulate the array (not a copy of the array) as an array of unsigned.
The code should build on platforms where it worked before (at least with sufficiently friendly compilers) and should not build on platforms where it can't work.
I have no control over which compiler is used and with which settings.
However this is not actually correct C since it's casting between pointers to different types.
Indeed, you cannot do such casts, because the two structure types are not compatible. You could however use a work-around such as this:
typedef union
{
struct data;
uint32_t array[10];
} internal_t;
...
void frobnicate(struct data *param) {
internal_t* internal = (internal_t*)param;
...
Another option if you can change the original struct declaration but not its member names, is to use C11 anonymous union:
struct data {
union {
int a[10];
uint32_t u32[10];
}
};
This means that user code accessing foo.a won't break. But you'd need C11 or newer.
Alternatively, you could use a uint32_t* to access the int[10] directly. This is also well-defined, since uint32_t in this case is the unsigned equivalent of the effective type int.
Is there a way I can add compile-time guards so that, for the rare people for whom int isn't “old-school” 32-bit, the code doesn't build?
The obvious is static_assert(sizeof(int) == 4, "int is not 32 bits"); but again this requires C11. If backwards compatibility with older C is needed, you can invent some dirty "poor man's static assert":
#define stat_assert(expr) typedef int dummy_t [expr];
#if INT_MIN != -0x80000000
Depending on how picky you are, this isn't 100% portable. int could in theory be 64 bits, but probably portability to such fictional systems isn't desired either.
If you don't want to drag limits.h around, you could also write the macro as
#if (unsigned int)-1 != 0xFFFFFFFF
It's a better macro regardless, since it doesn't have any hidden implicit promotion gems - note that -0x80000000 is always 100% equivalent to 0x80000000 on a 32 bit system.

Declare generic variable type

I am trying to declare a generic variable type in C (I can't us C++), and I have in my mind the following options.
Option1
typedef struct
{
void *value;
ElementType_e type;
} Data_t;
Option 2
typedef struct {
ElementType_e type;
union {
int a;
float b;
char c;
} my_union;
} my_struct;
where ElementType_e is an enum that holds all the possible type of variables (e.g. int, char, unsigned int, etc..). I am kinda leaning toward option 1, because I don't believe casting will add extra computational time, compared to switch, right?
I am just wondering which type is more useful? I know option 1 will require casting every-time being used/accessed. is there any possible issues that could happen with casting ( especially with running/compiling the code on different platform, e.g 32 bits and 16 bits micro)
While option2 require a switch () to do any operation (e.g. addition, ...).
The following link explained that Option 2 is better ( from readability point of view), but i mainly concern about the code size and computational cost.
Generic data type in C [ void * ]
is there any possible issues that could happen with casting
No, as you do not want cast, as there is no need to cast when assigning from/to a void-pointer (in C).
I am just wondering which type is more useful?
Both do, so it depends, as
1 is for the lazy (as it's few typing, and few different variables' names to remember).
2 is for the cautious (as it's type-save, as opposed to option 1, where the "real" type info is lost, so you can even assign a variable's address of a type not in ElementType_e).
Referring a comment:
Regarding performance I expect no major difference between both approaches (if implemented sanely), as both options need condtional statments on assigning to/from (exception here are pointer variables, which for option 1 go without conditonal statements for assignment).
I'd recommend using a union. In fact, I've used one myself in a similar situation:
union sockaddr_u {
struct sockaddr_storage ss;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
};
I use this union in socket code where I could be working with either IPv4 or IPv6 addresses. In this particular case, the "type" field is actually the first field in each of the inner structs (ss.ss_family, sin.sin_family, and sin6.sin6_family).
I think the problem is not well posed, since there are infinite possible data types definable by the programmer. Consider for example the following sequence:
typedef char S0_t;
typedef struct { S0_t x; } S1_t;
typedef struct { S1_t x; } S2_t;
typedef struct { S2_t x; } S3_t;
It's pretty clear that it's possible to follow indefinitely in order to define as many new types as we want.
So, there is not a straight manner to handle this possibilities.
On the other hand, as pointers are of more flexible nature, you can take the decision of defining a generic type concerned only with pointer types.
Thus, the types used in your project will have to be only pointers.
In this way, probably something very simple like the following definition could work:
typedef void* generic_t;

How to keep size of struct unchanged in x32 and x64?

So I have a structure with mixed data types like the below and I want to make sure that sizeof(struct a) is a multiple of the word size in x32 and x64. How can I do that? Thank you.
struct a {
vaddr_t v1;
size_t v2;
unsigned short v3;
struct b* v4;
struct a *v5;
int v6;
pthread_mutex_t lock;
};
With basic types, like ints or shorts, you could achieve this by explicitly using int32 or int16 instead of int or short. For other types like size_t or pointers, it gets more complicated. Your best bet is to use type attributes (http://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Type-Attributes.html).
If all that matters is the structure alignment in memory, align the structure itself, not its members.
I may be stepping a bit outside of my comfort zone here, however there seems to be a variation on the malloc called memalign thus :
void *memalign(size_t alignment, size_t size);
The memalign() function allocates size bytes on a specified
alignment boundary and returns a pointer to the allocated
block. The value of the returned address is guaranteed to be
an even multiple of alignment. The value of alignment must
be a power of two and must be greater than or equal to the
size of a word.
That may or may not exist on all platforms but this one seems to be very common :
int posix_memalign(void **memptr, size_t alignment, size_t size);
Seen at :
http://pubs.opengroup.org/onlinepubs/009695399/functions/posix_memalign.html
Now I would think that the datatypes for fixed width type declarations, as proposed by the ISO/JTC1/SC22/WG14 C, committee's working draft for the revision of the current ISO C standard ISO/IEC 9899:1990 Programming language - C, ( I read that in a manpage ) would be cross platform and cross architecture stable.
So if you looked into the lower levels of your struct members then hopefully they are based on things like int32_t or uint32_t for an integer. There are POSIX types such as :
/*
* POSIX Extensions
*/
typedef unsigned char uchar_t;
typedef unsigned short ushort_t;
typedef unsigned int uint_t;
typedef unsigned long ulong_t;
So I am thinking here that perhaps it is possible to construct your structs using only types that are defined as these totally cross platform stable datatypes and the end result being that the structs are always the same size regardless where or how you compile your code.
Please bear in mind, I am making a stretch here and hoping that someone else may clarify and perhaps correct my thinking.

What's the purpose of these `typedef`?

typedef intptr_t ngx_int_t;
typedef uintptr_t ngx_uint_t;
typedef intptr_t ngx_flag_t;
What can we benifit from this ?I can't think of one to be honest...
The above code are from the famous nginx project,check it if interested.
One of the typedef purposes is portability. E.g. different compilers and platforms have various type sizes, e.g. sizeof(int) on x86, Linux, gcc is not the same as on Texas Instrument's processors :) But it's still int.
So,
typedef int INT32
saves one when porting the code.
Another purpose of typedef, is to declare types in order to make shorter declarations.
typedef sharted_ptr<MyClass> MyClassPtr;
And now, you can use MyClassPtr as a type, instead of writing the whole shared_ptr... string.
And the very common usage of typedef with structures:
typedef struct {
int x;
int y;
} Point;
or
struct point {
int x;
int y;
}
typedef struct point Point;
Both typedefs let you avoid typing struct keyword every time.
It's often done for code portability, and is particularly relevant for embedded systems.
Suppose you have some integer values that absolutlely MUST be 32-bits long. Maybe they need to map to network/disk structures, maybe they need to hold values of that magnitude, or whatever.
Now, suppose you develop your code on a compiler where 'int' is 32 bits. You write...
struct s {
int a,b,c,d;
}
...and it works fine. But, if you need to switch to a compiler where int is only 16-bits, but long is 32, you would need to change all those declarations to
struct s {
long a,b,c,d;
}
Worse yet, you can't do just search/replace, because some of the 'ints' you probably don't care about the size. So, the best approach is to to this:
typedef long INT32; // change this typedef according to compiler
struct s {
INT32 a,b,c,d;
}
Then, all you need to is change the typedefs.
I know two reasons:
Aliasing, turning complex declaration something simpler
Portability, at different architecture, a type could be differently just, as very simple example: u32, where at some places could be defined as unsigned int, other unsigned long type.
The reason could be that they wish to change the pointer type when porting the code. On another system, there might be different addressing modes ("banking" etc), and then they might need to use non-standard syntax, like
typedef far intptr_t ngx_int_t;
If they never port the code to any system with more than one addressing mode on the same system, portability of pointers would never be an issue and the typedef would be redundant.
One of the reason I have seen people do this is that they think the if there is a need to change the actual type they just have to change the typedef. I am not too convined about that argument though.

Enforce strong type checking in C (type strictness for typedefs)

Is there a way to enforce explicit cast for typedefs of the same type? I've to deal with utf8 and sometimes I get confused with the indices for the character count and the byte count. So it be nice to have some typedefs:
typedef unsigned int char_idx_t;
typedef unsigned int byte_idx_t;
With the addition that you need an explicit cast between them:
char_idx_t a = 0;
byte_idx_t b;
b = a; // compile warning
b = (byte_idx_t) a; // ok
I know that such a feature doesn't exist in C, but maybe you know a trick or a compiler extension (preferable gcc) that does that.
EDIT
I still don't really like the Hungarian notation in general. I couldn't use it for this problem because of project coding conventions, but I used it now in another similar case, where also the types are the same and the meanings are very similar. And I have to admit: it helps. I never would go and declare every integer with a starting "i", but as in Joel's example for overlapping types, it can be life saving.
For "handle" types (opaque pointers), Microsoft uses the trick of declaring structures and then typedef'ing a pointer to the structure:
#define DECLARE_HANDLE(name) struct name##__ { int unused; }; \
typedef struct name##__ *name
Then instead of
typedef void* FOOHANDLE;
typedef void* BARHANDLE;
They do:
DECLARE_HANDLE(FOOHANDLE);
DECLARE_HANDLE(BARHANDLE);
So now, this works:
FOOHANDLE make_foo();
BARHANDLE make_bar();
void do_bar(BARHANDLE);
FOOHANDLE foo = make_foo(); /* ok */
BARHANDLE bar = foo; /* won't work! */
do_bar(foo); /* won't work! */
You could do something like:
typedef struct {
unsigned int c_idx;
} char_idx;
typedef struct {
unsigned int b_idx;
} byte_idx;
Then you would see when you are using each:
char_idx a;
byte_idx b;
b.b_idx = a.c_idx;
Now it is more clear that they are different types but would still compile.
What you want is called "strong typedef" or "strict typedef".
Some programming languages [Rust, D, Haskell, Ada, ...] give some support for this at language level, C[++] does not. There was a proposal to include it into the language with the name "opaque typedef", but was not accepted.
The lack of language support is really not a problem though. Just wrap the type to be aliased into a new class having exactly 1 data member, of type T. Much of the repetition can be factored out by templates and macros. This simple technique is just as convenient as in the programming languages with direct support.
Use a lint. See Splint:Types and strong type check.
Strong type checking often reveals
programming errors. Splint can check
primitive C types more strictly and
flexibly than typical compilers (4.1)
and provides support a Boolean type
(4.2). In addition, users can define
abstract types that provide
information hiding (0).
In C, the only distinction between user-defined types that is enforced by the compiler is the distinction between structs. Any typedef involving distinct structs will work. Your major design question is should different struct types use the same member names? If so, you can simulate some polymorphic code using macros and other scurvy tricks. If not, you are really committed to two different representations. E.g., do you want to be able to
#define INCREMENT(s, k) ((s).n += (k))
and use INCREMENT on both byte_idx and char_idx? Then name the fields identically.
You asked about extensions. Jeff Foster's CQual is very nice, and I think it could do the job you want.
With C++11 you can use an enum class, e.g.
enum class char_idx_t : unsigned int {};
enum class byte_idx_t : unsigned int {};
The compiler will enforce an explicit cast between the two types; it is like a thin wrapper class. Unfortunately you won't have operator overloading, e.g. if you want to add two char_idx_t together you will have to cast them to unsigned int.
If you were writing C++, you could make two identically defined classes with different names that were wrappers around an unsigned int. I don't know of a trick to do what you want in C.
Use strong typedef as defined in BOOST_STRONG_TYPEDEF

Resources