Author Topic: Idiomatic error handling in C  (Read 567 times)

0 Members and 1 Guest are viewing this topic.

Offline Lanny

  • Zealot
  • ****
  • Posts: 1,123
    • View Profile
Idiomatic error handling in C
« on: November 06, 2014, 05:43:45 am »
So I have the following code in C, a really straight forward hex string to integer conversion function:

Code: [Select]
#include <stdio.h>
#include <string.h>

int hexatoi(char *str, int *to) {
  int num = 0,
      i = 0,
      len = strlen(str),
      t;
  char c, b;

  if (len < 2 || len > 8 || str[0] != '0' || str[1] != 'x') {
    return 1;
  }

  while (str[i] != '\0') i++;

  i--;
  while(i > 1) {
    c = str[i];
    if (c >= '0' && c <= '9')
      b = c - '0';
    else if (c >= 'a' && c <= 'z')
      b = c - 'a' + 10;
    else if (c >= 'A' && c <= 'Z')
      b = c - 'A' + 10;
    else
      return 1;

    num |= (int)b << (len-1-i)*4;
    i--;
  }

  *to = num;

  return 0;
}

int main(int argc, char *argv[]) {
  int i;
  if (hexatoi(argv[1], &i)) {
    printf("Malformed input");
    return 1;
  }

  printf("%d\n", i);
  return 0;
}

and I'm wondering what the best way to say "your string is malformed" is. As you can see from the code the function takes a string and a pointer to an integer and assigns the result of the conversion at the pointer, using the return value to indicate if there was an error. I really hate this approach, taking a pointer and mutating it feels dirty to me. I want to just return the converted number but there's no possible value that couldn't be a valid output.

My other idea was to return a struct that has the value and a "there was an error" field, but I've never seen that before and feel like it would look pretty weird in C.

Is there a better way of handling this kind of situation.

Offline aldra

  • Arch Disciple
  • ***
  • Posts: 623
  • albrecht drais
    • View Profile
Re: Idiomatic error handling in C
« Reply #1 on: November 07, 2014, 01:32:59 am »
there's nothing inherently wrong with it, pointers ARE dirty.

if I'm reading that right though, you're converting a hex value (char*, format 0x000000, 64 bits) to an integer (int). why does the integer need to be a pointer?

the way I'd do it is send a pointer to the string to hexatoi, and have it return the converted number by value - an integer has a fixed memory allocation, so no need for a pointer - if the string is malformed you could return -1 or something so the main function can detect and report the failure.

Offline Lanny

  • Zealot
  • ****
  • Posts: 1,123
    • View Profile
Re: Idiomatic error handling in C
« Reply #2 on: November 07, 2014, 02:06:56 am »
the way I'd do it is send a pointer to the string to hexatoi, and have it return the converted number by value - an integer has a fixed memory allocation, so no need for a pointer - if the string is malformed you could return -1 or something so the main function can detect and report the failure.

That's what I would like to do but the issue is that -1 is would be the correct (non-error) return value for 0xFFFFFFFF (assuming two's complement) when the size of an int is 32 bits. This does mean that the function will produce different values on 32 vs. 64bit systems but it doesn't matter since the input represents a 32bit address and will be cast to unsigned down the line (realizing now that I should have made "to" an pointer to an unsigned int). There's a valid input that corresponds to every possible value of a 32 bit int, so it seems like I need to return more information to the caller than I can pack in one int. I thought about using long but I'm not actually guaranteed more than 32 bits (and on win32 systems only get 32) so the same problem exists.

Offline aldra

  • Arch Disciple
  • ***
  • Posts: 623
  • albrecht drais
    • View Profile
Re: Idiomatic error handling in C
« Reply #3 on: November 07, 2014, 02:11:45 am »
ah, fair enough.

in that case the only other simple solution I can think of would be to either pass control to the hexatoi function and have the error check/break in there to negate the need for the failure to be stored anywhere, or to create a third function to perform the error check and return good/bad, only progressing to hexatoi if the string passes.