dimanche 28 juin 2015

When to cast size_t

I'm a little confused as how to use size_t when other data types like int, unsigned long int and unsigned long long int are present in a program. I try to illustrate my confusion minimally. Imagine a program where I use

void *calloc(size_t nmemb, size_t size)

to allocate an array (one- or multidimensional). Let the call to calloc() be dependent on nrow and sizeof(unsigned long int). sizeof(unsigned long int) is obviously fine because it returns size_t. But let nrow be such that it needs to have type unsigned long int. What do I do in such a case? Do I cast nrow in the call to calloc() from unsigned long int to size_t?

Another case would be

char *fgets(char *s, int size, FILE *stream)

fgets() expects type int as its second parameter. But what if I pass it an array, let's say save, as it's first parameter and use sizeof(save) to pass it the size of the array? Do I cast the call to sizeof() to int? That would be dangerous since int isn't guaranteed to hold all possible returns from sizeof().

What should I do in these two cases? Cast, or just ignore possible warnings from tools such as splint?

Here is an example regarding calloc() (I explicitly omit error-checking for clarity!):

long int **arr;
unsigned long int mrow;
unsigned long int ncol;

arr = calloc(mrow, sizeof(long int *));

for(i = 0; i < mrow; i++) {
        arr[i] = calloc(ncol, sizeof(long int));
}

Here is an example for fgets() (Error-handling again omitted for clarity!):

char save[22];
char *ptr_save;
unsigned long int mrow
if (fgets(save, sizeof(save), stdin) != NULL) {
        save[strcspn(save, "\n")] = '\0';
        mrow = strtoul(save, &ptr_save, 10);
}

Aucun commentaire:

Enregistrer un commentaire