How do I determine the underlying type?

B

Bob Williamson

Hi. How can I determine the underlying type of typedefs? For example the
stat structure has various fields in it. Suppose I want to know what dev_t
is, where can I find it? If I look in stat.h it's all gobbledygook to
me. Ideally I would like a tool to be able to tell me what the type is for
any typedef'd name. Is there anything like that?

Thanks,
Bob
 
K

Kenny McCormack

Hi. How can I determine the underlying type of typedefs? For example the
stat structure has various fields in it. Suppose I want to know what dev_t
is, where can I find it? If I look in stat.h it's all gobbledygook to
me. Ideally I would like a tool to be able to tell me what the type is for
any typedef'd name. Is there anything like that?

Thanks,
Bob

There's obviously no "standard C" way to do this, so this is all obviously
off-topic. Or, in the words of the members of this group:
Off topic. Not portable. Cant discuss it here. Blah, blah, blah.
(see sig for useful links)

But, if what you're really asking is "Can I dump out a struct's layout with
typedefs expanded?", and you are running a Debian-like Linux system (a
reasonable assumption, though not 100%, of course), then I think you might
like to look for a file called something like: dwarves_1.10-2_*.deb

Somewhere in there (in the "dwarves" utils) is a tool, whose name escapes
me at the moment, since it's been a while since I've played with it, that
does a very nice job on this task. I have faith you will be able to fill
in the missing details in this description.

--
Useful clc-related links:

http://en.wikipedia.org/wiki/Aspergers
http://en.wikipedia.org/wiki/Clique
http://en.wikipedia.org/wiki/C_programming_language
 
M

Malcolm McLean

Hi. How can I determine the underlying type of typedefs? For example the
stat structure has various fields in it. Suppose I want to know what dev_t
is, where can I find it? If I look in stat.h it's all gobbledygook to
me. Ideally I would like a tool to be able to tell me what the type is for
any typedef'd name. Is there anything like that?
Standard headers tend to be like that. They define things in strange ways,
often with compiler-specific preprocessing instructions or tags.
For a standard function, look up the documentation.

For a non-standard function, the answer is a bit different. Normally a decent
IDE will list fields of a structure for you, often by right-clicking or
hovering.
 
J

James Kuyper

Hi. How can I determine the underlying type of typedefs? For example the
stat structure has various fields in it. Suppose I want to know what dev_t
is, where can I find it? If I look in stat.h it's all gobbledygook to
me. Ideally I would like a tool to be able to tell me what the type is for
any typedef'd name. Is there anything like that?

The C standard provides no such tool. However, I've used two different
debuggers which support the 'whatis' command, which will explain to you
the type of a specified expression.
 
I

Ike Naar

Hi. How can I determine the underlying type of typedefs? For example the
stat structure has various fields in it. Suppose I want to know what dev_t
is, where can I find it? If I look in stat.h it's all gobbledygook to
me. Ideally I would like a tool to be able to tell me what the type is for
any typedef'd name. Is there anything like that?

One can use the C preprocessor to do some of the dirty work.
Here's what I did to find the underlying type of dev_t on
the machine I'm currently using:

1) Created a one-line C file that includes the header for 'stat':

/* begin a.c */
#include <sys/stat.h>
/* end a.c */

2) ran this file through the C preprocessor, and searched for
the word 'dev_t':

CC -E a.c | grep -w dev_t

which produced the following output:

typedef __uint64_t dev_t;
dev_t st_dev;
dev_t st_rdev;
int mknod(const char *, __mode_t, dev_t) __asm("__mknod50");

The answer is on the first line of output.
 
I

Ike Naar

2) ran this file through the C preprocessor, and searched for
the word 'dev_t':

CC -E a.c | grep -w dev_t

Sorry, an editing error appears on the line above, 'CC' should be 'cc'.
 
B

Bob Williamson

One can use the C preprocessor to do some of the dirty work.
Here's what I did to find the underlying type of dev_t on
the machine I'm currently using:

1) Created a one-line C file that includes the header for 'stat':

/* begin a.c */
#include <sys/stat.h>
/* end a.c */

2) ran this file through the C preprocessor, and searched for
the word 'dev_t':

CC -E a.c | grep -w dev_t

which produced the following output:

typedef __uint64_t dev_t;
dev_t st_dev;
dev_t st_rdev;
int mknod(const char *, __mode_t, dev_t) __asm("__mknod50");

The answer is on the first line of output.

Ike thank you very much for taking the time to answer my question. On my
Linux using gcc it took a bit longer but I am getting closer with your help.

bobw@home/tmp$ cat a.c
#include <sys/stat.h>

bobw@home/tmp$ gcc -E a.c | grep -w dev_t
typedef __dev_t dev_t;

bobw@home/tmp$ gcc -E a.c | grep -w __dev_t
__extension__ typedef __u_quad_t __dev_t;
typedef __dev_t dev_t;
__dev_t st_dev;
__dev_t st_rdev;
extern int mknod (__const char *__path, __mode_t __mode, __dev_t __dev)
__dev_t __dev) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2)));
__dev_t *__dev) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (2, 4)));
__mode_t __mode, __dev_t *__dev)

bobw@home/tmp$ gcc -E a.c | grep -w __u_quad_t
__extension__ typedef unsigned long long int __u_quad_t;
__extension__ typedef __u_quad_t __dev_t;
__extension__ typedef __u_quad_t __ino64_t;
__extension__ typedef __u_quad_t __rlim64_t;
__extension__ typedef __u_quad_t __fsblkcnt64_t;
__extension__ typedef __u_quad_t __fsfilcnt64_t;
bobw@home/tmp$

I am not sure how to interpret this output. Is dev_t unsigned long or long int?

Thanks,
Bob
 
J

James Kuyper

On 06/27/2013 02:39 PM, Bob Williamson wrote:
....
bobw@home/tmp$ cat a.c
#include <sys/stat.h>

bobw@home/tmp$ gcc -E a.c | grep -w dev_t
typedef __dev_t dev_t;

bobw@home/tmp$ gcc -E a.c | grep -w __dev_t
__extension__ typedef __u_quad_t __dev_t; ....

bobw@home/tmp$ gcc -E a.c | grep -w __u_quad_t
__extension__ typedef unsigned long long int __u_quad_t; ....

I am not sure how to interpret this output. Is dev_t unsigned long or long int?

dev_t is a typedef for __dev_t. __dev_t is a typedef for __u_quad_t.
__u_quad_t is a typedef for unsigned long long int. "long long" is a
type specifier that was introduced in C99, 14 years ago. It's guaranteed
to be at least 64 bits in size.
 
B

Bob Williamson

On 06/27/2013 02:39 PM, Bob Williamson wrote:
...

dev_t is a typedef for __dev_t. __dev_t is a typedef for __u_quad_t.
__u_quad_t is a typedef for unsigned long long int. "long long" is a
type specifier that was introduced in C99, 14 years ago. It's guaranteed
to be at least 64 bits in size.

James thank you for clarifying this for me. I am not a C programmer so I did
not know that. I want to understand what gcc is doing on Linux. Ike's idea
and your explanation here helped quite a bit. Thanks for mentioning the
debugger angle earlier but something static like this helps me a lot more.

Thanks,
Bob
 
S

Stephen Sprunk

Ike thank you very much for taking the time to answer my question.
On my Linux using gcc it took a bit longer but I am getting closer
with your help.

...
typedef __dev_t dev_t;
...
__extension__ typedef __u_quad_t __dev_t;
...
__extension__ typedef unsigned long long int __u_quad_t;
...

I am not sure how to interpret this output. Is dev_t unsigned long
or long int?

Neither; it is "unsigned long long int".

You may not be familiar with "long long int", which is an integer type
added in C99 that is (at least) 64-bit; in contrast, a "long int" is (at
least) 32-bit, and "int" and "short int" are (at least) 16-bit.

Most modern implementations make "int" larger than required, and some
also make "long int" larger than required, but you cannot rely on that
in portable code. While _your_ system may have 64-bit long ints (and
even 64-bit ints!), another may have only 32-bit long ints (and maybe
even 16-bit ints!), so if you need a type that is guaranteed to be (at
least) 64-bit, you should use long long int.

S
 
E

Eric Sosman

James thank you for clarifying this for me. I am not a C programmer so I did
not know that. I want to understand what gcc is doing on Linux. Ike's idea
and your explanation here helped quite a bit. Thanks for mentioning the
debugger angle earlier but something static like this helps me a lot more.

Keep in mind that this definition of dev_t is specific to
the particular implementation you're using. That implementation
defines dev_t (eventually) as unsigned long long int, but other
implementations might use something else: unsigned long int, or
unsigned int, perhaps plain unadorned int, or possibly something
quite strange indeed. That's the reason for using names like
`dev_t' in the first place: You don't need to learn the details
of how every (POSIX-conforming) system on the planet encodes its
device identifiers. In a sense, dev_t is like a contract or an
interface: You just utter the magic word `dev_t', and the local
system's header files declare it as the Right Thing for the local
customs, matching up with the encodings the library traffics in.

Some other examples of this sort of thing are size_t (an integer
of some kind or other that can count any object's bytes), time_t
(some sort of arithmetic type that can represent times and dates),
and FILE (some unspecified sort of thing that holds the information
necessary to read and write data). All of these are likely to resolve
to different fundamental types on different systems, but as long as
you use the "abstract" names you'll get the right result on any system.

So in a sense, the type underlying dev_t is ... dev_t!
 
K

Keith Thompson

Ike Naar said:
One can use the C preprocessor to do some of the dirty work.
Here's what I did to find the underlying type of dev_t on
the machine I'm currently using:

1) Created a one-line C file that includes the header for 'stat':

/* begin a.c */
#include <sys/stat.h>
/* end a.c */

2) ran this file through the C preprocessor, and searched for
the word 'dev_t':

CC -E a.c | grep -w dev_t

Should be cc, as you pointed out in a followup.
which produced the following output:

typedef __uint64_t dev_t;
dev_t st_dev;
dev_t st_rdev;
int mknod(const char *, __mode_t, dev_t) __asm("__mknod50");

The answer is on the first line of output.

At least for gcc, and assuming a Unix-like sysetm, this is a bit simpler:

echo '#include <sys/stat.h>' | gcc -E - | grep -w dev_t

Though the output on my system is less illuminating:

typedef __dev_t dev_t;

You might need to iterate to find the actual definition.
 
B

Bob Williamson

Just out of curiosity: why do you need to know the underlying type of dev_t?

To use the stat interface from a different language. Thanks to you and
everyone who answered.

Bob
 
B

BartC

Bob Williamson said:
To use the stat interface from a different language. Thanks to you and
everyone who answered.

sizeof(dev_t) might be sufficient in that case.
 
B

Bob Williamson

sizeof(dev_t) might be sufficient in that case.

Bart thanks for your posting. It wouldn't be sufficient but it helps. We
would need to know what kind of data the field contains, signed/unsigned
etc. I'll add this to our list.

Bob
 
B

BartC

Bob Williamson said:
Bart thanks for your posting. It wouldn't be sufficient but it helps. We
would need to know what kind of data the field contains, signed/unsigned
etc. I'll add this to our list.

OK, but my experience of dealing with APIs/etc specified in C is that the
size of a type is more important than its signedness! (So that you can build
correctly matching structs in the other language, although padding also
needs to correspond, push the right number of bytes in function calls, etc).

And you can't tell, in C, the size of most int types, without looking at the
specs for an implementation or using sizeof(). I don't know if a macro such
as issigned() can be created to tell you an int type's signedness.
 
K

Keith Thompson

BartC said:
OK, but my experience of dealing with APIs/etc specified in C is that the
size of a type is more important than its signedness! (So that you can build
correctly matching structs in the other language, although padding also
needs to correspond, push the right number of bytes in function calls, etc).

And you can't tell, in C, the size of most int types, without looking at the
specs for an implementation or using sizeof(). I don't know if a macro such
as issigned() can be created to tell you an int type's signedness.

#define IS_SIGNED(type) ((type)-1 < (type)0)
#define IS_FLOATING(type) ((type)1 / 2 != 0)

Untested.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top