The size_t Variable Type

The C language has its basic variable types: char, int, float, double, struct, and that oddball newbie _Bool. Anything else you see as a “variable” is probably a convenient shortcut manufactured by using a typedef statement. Some of these typedef variables are faily standard, including the most common one, size_t.

The typedef operator creates a convenient shortcut for a variable type. It’s similar to the #define preprocessor directive in that it’s valid only in the code where it’s used.

Most frequently, typedef creates shortcuts for structure variables, but many header files use typedef to create special names for specific variable types, such as size_t. Specifically, the size_t variable type is related to the sizeof operator, which returns the size of a memory object in bytes.

In the original K&R book, a byte is defined as the size of a char variable: One byte of memory equals one char-sized value. When the sizeof operator returns 4, you know that the object occupies 4 bytes (chars) of memory.

When Drs. Kernighan and Ritchie updated their book to cover ANSI C, they introduced the size_t variable as the type of value returned from the sizeof operator. It’s defined, or typedef‘d, as an unsigned int value, usually an unsigned long. The value represents the size (in bytes) of a chunk of memory. So, whenever you see the size_t variable in a function prototype, it means that the function somehow deals with a chunk of memory.

For example, the malloc() function uses a size_t argument to set aside a chunk of memory:

void * malloc(size_t size);

The size_t value also appears in some string function prototypes:

size_t strlen(const char *s);

The strlen() function returns the length of a string, which is really a value describing (almost) how many bytes (chars) of storage the string occupies. (The value returned from strlen() doesn’t account for the null character at the end of the string.)

It’s common practice to use an int variable when a size_t value is specified, though this approach isn’t best. First, size_t is an unsigned value; you can’t have negative memory storage. Second, you must use the proper variable type with a function, lest you get into trouble.

When a function calls for a size_t variable, I recommend declaring any associated variables as size_t values, not an int, unsigned long, or unsigned int:

size_t msize,mnew,and,so,on;

The variables defined above are created as size_t types.

Another good practices is to use the proper placeholder in a printf() statement to display a size_t value. Remember, the value isn’t an int: When you use the %d placeholder, the compiler whines at you. That’s because the %d placeholder represents a signed value.

In my code, I use %lu (long unsigned):

#include <stdio.h>
  
int main()
{
    printf("An int uses %lu bytes of storage.\n",
            sizeof(int)
          );

    return(0);
}

The C99 standard established the %z placeholder prefix for size_t values. You postfix the %z with a d or u, as in %zu or %zd, to properly display a size_t value.

Other typedef values are used in various C language functions, such as the time_t values found in time.h functions. As with size_t, ensure that you create time_t variables for use with these functions. Using unsigned int values is okay, and I’ve done so in my code, but setting the proper variable type reduces the potential for errors.

2 thoughts on “The size_t Variable Type

  1. I really don’t like to disagree with or criticize K&R but I am sceptical about the usefulness or wisdom of using typedef for what is nothing more than an alias. I cannot see what “hiding” the underlying type of the variable achieves.

    Every variable has some meaning beyond it’s type – physical dimensions, amounts of money, angles and so on. You could extend the size_t principle to create a large number of typedefs for all of these but to do so would be absurd.

    My feeling is that the meaning of variables and function return types should be expressed in variable names and function names, not typedefs.

  2. In keeping with a low-level language, having a minimum of variable types makes sense, so I can see K&R’s logic at that level. And I’ve never used typedef in any of my code, not even for structures.

    I’ve thought about this issue and to me it makes sense from a consistency standpoint. For example, the original size_t might have been assigned to an unsigned int for the 16-bit operating systems of the day. When 32-bit came out, all the developer needed to do was redefine the typedef to an unsigned long. That’s a single change at one location in a header file that affects all related variables. Otherwise, the entire code must be combed for memory-size variables and each must be retyped. Odds of missing one or two is great.

    From that perspective, using a typedef makes sense. Still, I agree with you that if a variable type is that important, just hard-code it.

Leave a Reply