**Overflow** Using `int` can have trouble with integers as small as 64k. Consider a version using a time stamp of 14 digits as one of the fields `20220302101901`. Use some _unsigned_ type, perhaps `uintmax_t`. Even then I would consider _detecting_ overflow. **What if non-digit or non-dot?** Since separators like `,`, and letters are treated pathologically like digits, how about giving those meaning as separators and not use them to computer the version value? // while (*v1 && *v1 != '.') a = 10*a + (*v1++ - '0'); while (isdigit(*v1)) a = 10*a + (*v1++ - '0'); Pedantically, should use `unsigned char` values with `is...()` while (isdigit(*(const unsigned char*)v1)) a = 10*a + (*v1++ - '0'); ... or use `(*v1 >= '0' && *v1 <= '9')` if avoiding libraries. **NULL?** Since version compare is often done near the beginning of code and the result is _very_ important, I'd like the compare to tolerate more of the usual mistakes like `NULL` or effect some error message. int compareVersion(const char * v1, const char * v2) { if (v1 == NULL) v1 = ""; if (v2 == NULL) v2 = ""; ...