Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C structure syntax

Tags:

c

syntax

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?

like image 461
Ccorock Avatar asked May 16 '15 16:05

Ccorock


People also ask

What is structure in C with syntax?

Structures (also called structs) are a way to group several related variables into one place. Each variable in the structure is known as a member of the structure. Unlike an array, a structure can contain many different data types (int, float, char, etc.).

What Is syntax for structure?

Syntax to Define a Structure in CstructName: This is the name of the structure which is specified after the keyword struct. data_Type: The data type indicates the type of the data members of the structure. A structure can have data members of different data types.

What is structure in C with example?

struct structureName { dataType member1; dataType member2; ... }; For example, struct Person { char name[50]; int citNo; float salary; }; Here, a derived type struct Person is defined.

How do you initialize a structure in C?

Structure members can be initialized using curly braces '{}'.


3 Answers

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.

like image 113
antron Avatar answered Oct 15 '22 15:10

antron


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.

like image 1
Drew Dormann Avatar answered Oct 15 '22 13:10

Drew Dormann


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.

like image 1
chqrlie Avatar answered Oct 15 '22 13:10

chqrlie