Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I convert to size_t from int safely?

Assigning an int to a size_t (or using it in malloc) in GCC produces the following warning:

warning: conversion to 'size_t' from 'int' may change the sign of the result [-Wsign-conversion]

To solve this, I would like to wrap the conversion in a function that first checks if the conversion is valid, then does the cast.

This is what I have so far:

/* Convert int src to size_t dst. */
/* Assumes dst points to valid size_t address. */
int safe_size_t_from_int(size_t *dst, int src) {
    if(src < 0) return SAFE_ERROR_NEGATIVE;
    if(SIZE_MAX < INT_MAX) {
        if(src > (int)SIZE_MAX) return SAFE_ERROR_OVERFLOW;
    }
    *dst = (size_t)src;
    return SAFE_SUCCESS;
}

Am I missing anything? Is there a library with safe conversions that already exists?

The closest thing I can find is Microsoft Intsafe.h, but it appears to be for Win32 types only.

EDIT Modified as per chux' comment.

like image 819
Martin Avatar asked Dec 15 '14 18:12

Martin


1 Answers

To avoid compiler warnings in GCC, limit the action performed by a single cast operation to one of the following:

  1. truncation or extension
  2. cast away signed-ness or unsigned-ness
  3. cast away const-ness or non-const-ness

size_t is always an unsigned type large enough to hold a void pointer. Casting from int to size_t involves two cast operations: extend, then cast away signed-ness.

Here's two functions that produce no compiler warnings (with '-Wall -Werror -Wextra') on GCC 4.8.3. They return failure inline (via sentinel values), rather than in an extra return parameter.

int size_t2int(size_t val) {
    return (val <= INT_MAX) ? (int)((ssize_t)val) : -1;
}

size_t int2size_t(int val) {
    return (val < 0) ? __SIZE_MAX__ : (size_t)((unsigned)val);
}
like image 145
dembones Avatar answered Nov 02 '22 04:11

dembones