why define size_t ssize_t ?

W

William Xuuu

Hi,

This's a way of defining size_t and ssize_t in Linux:

//"linux/types.h"
typedef __kernel_size_t size_t;
typedef __kernel_ssize_t ssize_t;

//"asm/posix_types.h"
typedef unsigned int __kernel_size_t;
typedef int __kernel_ssize_t;

It seems so tricky to me. What benefits do we get from such a tricky
typedef ? better name (size_t is shorter than unsigned int) ?

thanks.
 
I

Ivan Vecerina

William Xuuu said:
This's a way of defining size_t and ssize_t in Linux:

//"linux/types.h"
typedef __kernel_size_t size_t;
typedef __kernel_ssize_t ssize_t;

//"asm/posix_types.h"
typedef unsigned int __kernel_size_t;
typedef int __kernel_ssize_t;

It seems so tricky to me. What benefits do we get from such a tricky
typedef ? better name (size_t is shorter than unsigned int) ?

On some 64-bit platforms, 'int' and 'unsigned int' may be 32-bits,
while addresses and even memory sizes could require 64 bits
(e.g. for the size of an allocated memory block > 4GB).
On such platforms, size_t could be typedef'd to a different
type, such as 'unsigned long long'.

Note also that 'size_t' is a typedef required by the ISO C standard
(it must be available if <stddef.h> is included). However, 'ssize_t'
does not exist in the C standard -- the standard 'ptrdiff_t'
typedef is nearly equivalent.

hth,
Ivan
 
I

infobahn

William said:
Hi,

This's a way of defining size_t and ssize_t in Linux:

//"linux/types.h"
typedef __kernel_size_t size_t;
typedef __kernel_ssize_t ssize_t;

//"asm/posix_types.h"
typedef unsigned int __kernel_size_t;
typedef int __kernel_ssize_t;

It seems so tricky to me. What benefits do we get from such a tricky
typedef ? better name (size_t is shorter than unsigned int) ?

On ssize_t I have no comment, since the C language's definition
does not incorporate such a type.

The size_t type is defined by ISO for use by functions such as
malloc and strlen (among others, of course), for representing
size information. It is required to be an unsigned integral
type, but need not be unsigned int. It could equally be
unsigned long or unsigned long long on some systems. It could
even (perhaps a touch pathologically) be unsigned char!

Consider the following code:

size_t len = strlen(s);

If we didn't have size_t, and wanted our code to run on the Zag,
Zeg, Zig, Zog, and Zug compilers, all of which have different
types to represent the size returned by strlen, we'd have to do
something like:

#if _ZAG
unsigned char len = strlen(s);
#elif _ZEG
unsigned short len = strlen(s);
#elif _ZIG
unsigned int len = strlen(s);
#elif _ZOG
unsigned long len = strlen(s);
#elif _ZUG
unsigned long long len = strlen(s);
#else
#error Unsupported platform.
#endif

The obvious step would be to add a typedef to handle this:

#if _ZAG
typedef unsigned char size_type;
#elif _ZEG
typedef unsigned short size_type;
#elif _ZIG
typedef unsigned int size_type;
#elif _ZOG
typedef unsigned long size_type;
#elif _ZUG
typedef unsigned long long size_type;
#else
#error Unsupported platform.
#endif

size_type len = strlen(s);

This is still a nuisance, although not such a bad nuisance, because
we can hide the cpp nonsense in a header.

If only we could persuade each implementor to include a standard
definition for strlen's return type, and put it in, say, stddef.h.
Then we wouldn't have to put all this nonsense in our own header,
and our code would be simpler as a result (and easier to port).

We're in luck. Fortunately, the C Standard actually /requires/
conforming implementations to do this; the name they settled on
was size_t.

I hope that answers your question.
 
J

Jonathan Burd

William said:
Hi,

This's a way of defining size_t and ssize_t in Linux:

//"linux/types.h"
typedef __kernel_size_t size_t;
typedef __kernel_ssize_t ssize_t;

//"asm/posix_types.h"
typedef unsigned int __kernel_size_t;
typedef int __kernel_ssize_t;

It seems so tricky to me. What benefits do we get from such a tricky
typedef ? better name (size_t is shorter than unsigned int) ?

thanks.

Remember to use `size_t` as the type for indexing variables
used to index into C-strings. For example,

#include <stdio.h>

int
main ()
{
size_t index;
char * foo = "Example string.";

for (index = 0; index < (size_t) 5; ++index)
(void) putchar (foo[ index ]);

return 0;
}

Just my two cents. :)

Regards,
Jonathan.
 
O

Old Wolf

Jonathan said:
Remember to use `size_t` as the type for indexing variables
used to index into C-strings. For example,

#include <stdio.h>

int
main ()
{
size_t index;
char * foo = "Example string.";

char const *foo = "Example string.";
for (index = 0; index < (size_t) 5; ++index)

Obfuscatory cast. 5 will be converted to size_t anyway.
Admittedly there are inferior compilers that will
issue a warning for signed-unsigned comparison in the
case of (index < 5).

(void) putchar (foo[ index ]);

useless cast. Sorry, but I disagree with the philosophy
of putting (void) before every unused return value. It
adds volumes of useless crap to your source code and
achieves almost nothing. If you want to search your code
for failure to check malloc's return value then you can
grep for malloc, etc.
 
K

Keith Thompson

infobahn said:
Consider the following code:

size_t len = strlen(s);

If we didn't have size_t, and wanted our code to run on the Zag,
Zeg, Zig, Zog, and Zug compilers, all of which have different
types to represent the size returned by strlen, we'd have to do
something like:

#if _ZAG
unsigned char len = strlen(s);
#elif _ZEG
unsigned short len = strlen(s);
#elif _ZIG
unsigned int len = strlen(s);
#elif _ZOG
unsigned long len = strlen(s);
#elif _ZUG
unsigned long long len = strlen(s);
#else
#error Unsupported platform.
#endif

Actually, if strlen() returned some unknown unsigned type, we could
just use:

unsigned long long len = strlen(s);

and let the result be converted implicitly. (It gets slightly more
complex if we need to worry about implementations that don't support
long long).

But of course size_t is still a useful thing to have.
 
J

Jonathan Burd

Old said:
Jonathan said:
Remember to use `size_t` as the type for indexing variables
used to index into C-strings. For example,

#include <stdio.h>

int
main ()
{
size_t index;
char * foo = "Example string.";


char const *foo = "Example string.";

for (index = 0; index < (size_t) 5; ++index)


Obfuscatory cast. 5 will be converted to size_t anyway.
Admittedly there are inferior compilers that will
issue a warning for signed-unsigned comparison in the
case of (index < 5).


(void) putchar (foo[ index ]);


useless cast. Sorry, but I disagree with the philosophy
of putting (void) before every unused return value. It
adds volumes of useless crap to your source code and
achieves almost nothing. If you want to search your code
for failure to check malloc's return value then you can
grep for malloc, etc.

return 0;
}

Perhaps, splint should be a bit more forgiving in that case.
 
W

William Xuuu

infobahn said:
On ssize_t I have no comment, since the C language's definition
does not incorporate such a type.

The size_t type is defined by ISO for use by functions such as
malloc and strlen (among others, of course), for representing

Hmm, thanks.

So i.e, for portable reasons, some special functions concerning with
memeory or address manipulations need size_t.

[...]
 

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,995
Messages
2,570,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top