Binary string to integer and integer to binary string I am working through K&amp;R for review and I thought that I would write some of my own routines for conversion of binary strings to int and int to binary string. I realize this is reinvetning the wheel; I am just doing this for fun. Also, I am attempting to follow this coding style CodingStyle.txt. Any and all critiques are welcomed.

#include &lt;mybin.h&gt;
#include &lt;limits.h&gt;
#include &lt;errno.h&gt;

/*
Parameters:
s   - String with a maximum of 63 binary digits
Return:
    - Decimal value of the binary string pointed to by s
Error:
    - Negative returned on error check errno
*/
signed long binstr2int(char *s)
{
    signed long rc;
    for (rc = 0; '\0' != *s; s++) {
        if (rc &gt; (LONG_MAX/2)) {
            errno = ERANGE;
            return -1;
        } else if ('1' == *s) {
            rc = (rc * 2) + 1;
        } else if ('0' == *s) {
            rc *= 2;
        } else {
            errno = EINVAL;
            return -1;
        }
    }
    return rc;
}

/*
Parameters:
num - The number to convert to a binary string
s   - Pointer to a memory region to return the string to
len - Size in bytes of the region pointed to by s
Return:
    - Pointer to the beginning of the string
Error:
    - NULL returned on error check errno
*/
char *int2binstr(unsigned long num, char *s, int len)
{   
    if (len &lt; 2) {
        errno = ERANGE;
        *s = '\0';
        return s;
    } else if (0 == num) {
        s[--len] = '\0';
        s[--len] = '0';
        return s + len;
    } else { 
        for (s[--len] = '\0'; 0 != num; num &gt;&gt;= 1) {
            if (0 == len) {
                errno = ERANGE;
                *s = '\0';
                return s;
            } else if (num &amp; 1) {
                s[--len] = '1';
            } else {
                s[--len] = '0';
            }
        }
    }
    return s + len;
}


Edit 1:
Okay, here is the revised code. Most of the suggestions I agree with. I did retain filling the buffer from end to beginning because it seems like a logical flow to me and requires one less variable to deal with. 


The do while suggestion was spot on. The for loop was unusual and the do while consumed one of the conditionals making the code easier to read.
The names of the functions have been revised so they are not misleading
The functions now handle unsigned long ints
ul2binstr now returns NULL on error. So this needs to be checked. 
Also the string parameter was in binstr2ul was made const
The len parameter was changed to size_t type




/*
Parameters:
s   - String with a maximum of log2(ULONG_MAX) binary characters
num - Memory address to store the result in
Return:
    - Status integer
Error:
    - Negative returned on error check errno
*/
int binstr2ul(const char *s, unsigned long *num)
{
    unsigned long rc;
    for (rc = 0; '\0' != *s; s++) {
        if (rc &gt; (ULONG_MAX/2)) {
            errno = ERANGE;
            return -1;
        } else if ('1' == *s) {
            rc = (rc * 2) + 1;
        } else if ('0' == *s) {
            rc *= 2;
        } else {
            errno = EINVAL;
            return -1;
        }
    }
    *num = rc;
    return 0;
}

/*
Parameters:
num     - The number to convert to a binary string
s       - Pointer to a memory region to return the string to
len     - Size in bytes of the region pointed to by s
Return:
        - Pointer to the beginning of the string
Error:
        - NULL returned on error check errno
*/
char *ul2binstr(unsigned long num, char *s, size_t len)
{
    if (0 == len) {
        errno = EINVAL;
        return NULL;
    } else {
        s[--len] = '\0';
    }

    do {
        if (0 == len) {
            errno = ERANGE;
            return NULL;
        } else {
            s[--len] = ((num &amp; 1) ? '1' : '0');
        }
    } while ((num &gt;&gt;= 1) != 0);

    return s + len;
}
It makes sense for the two functions to be symmetrical - ie that you can call
them in turn to swap between integer and string representations.  So I would
make binstr2int produce an unsigned long of full range returned through a
parameter and have the function return the status (0/-1):

int binstr2int(const char *s, unsigned long &amp;num);


Note that s can be const.

In int2binstr I think the characters should be moved to the beginning of the
string - this is what all other C string functions do (or at least I'm
ignorant of any that do not).  Also, your code is a bit awkward in
that it treats 0 separately from all other numbers.  This is a case where a
do {...} while loop makes sense as it can handle the zero case as any other
number and test for zero once it has done it:

char* int2binstr(unsigned long num, char *s, size_t size)
{
    long len = (long) size - 1;
    do {
        if (len &lt;= 0) {
            errno = ERANGE;
            return NULL;
        }
        s[--len] = (num &amp; 1) ? '1' : '0';
    } while ((num &gt;&gt;= 1) != 0);

    long n = (long) size - len - 1;
    memmove(s, s + len, n);
    s[n] = '\0';
    return s;
}


Here you can see that the tests for a short input string and for 
num == 0 are handled naturally.  Also I moved the string into place after
creating it.