Your sscanf is failing. When this happens, it leaves the arguments in an indeterminate state. So your return statement returns garbage.
%uhh means to read into an unsigned int , and then match the letter 'h' twice. If your input string did not actually contain h after the first number, then matching fails and sscanf will return 1 (or 0 if there wasn't even a first number).
You probably meant %hhu, to read an integer and store in an unsigned char, however you also need to make ipbytes be unsigned char to match the format specifier. The specifier for plain or signed char is %hhd.
This array should be unsigned anyway, otherwise your | later on is going to mess up (remember that negative numbers have a lot of 1 bits set, in 2's complement).
A further problem is that if your system has 32-bit int, then even when using unsigned char, the expression ipbytes[3] << 24 causes undefined behaviour if the high bit of ipbytes[3] is set, due to signed integer overflow: the integer promotions unfortunately promote unsigned char to a signed int.
Finally, if the system has 16-bit int then the << 16 and << 24 fail entirely.
A robust way to write the function would be to avoid any undesirable promotions:
uint32_t parseIPV4string(char const * ipAddress)
{
unsigned int ip[4];
if ( 4 != sscanf(ipAddress, "%u.%u.%u.%u", &ip[0], &ip[1], &ip[2], &ip[3]) )
return 0; // or some other indicator or error
return ipbytes[3] + ipbytes[2] * 0x100 + ipbytes[1] * 0x10000ul + ipbytes[0] * 0x1000000ul;
}
If you really want to use | and << then you either have to use some ugly casts; or change ip to have the type uint32_t in which case "%u" must be replaced by "%" SCNu32.