Does C have an equivalent of std::less from C++?

后端 未结 3 1189
小鲜肉
小鲜肉 2020-12-18 17:47

I was recently answering a question on the undefined behaviour of doing p < q in C when p and q are pointers into different objects

3条回答
  •  情书的邮戳
    2020-12-18 18:33

    I once tried to find a way around this and I did find a solution that works for overlapping objects and in most other cases assuming the compiler does the "usual" thing.

    You can first implement the suggestion in How to implement memmove in standard C without an intermediate copy? and then if that doesn't work cast to uintptr (a wrapper type for either uintptr_t or unsigned long long depending on whether uintptr_t is available) and get a most-likely accurate result (although it probably wouldn't matter anyway):

    #include 
    #ifndef UINTPTR_MAX
    typedef unsigned long long uintptr;
    #else
    typedef uintptr_t uintptr;
    #endif
    
    int pcmp(const void *p1, const void *p2, size_t len)
    {
        const unsigned char *s1 = p1;
        const unsigned char *s2 = p2;
        size_t l;
    
        /* Check for overlap */
        for( l = 0; l < len; l++ )
        {
            if( s1 + l == s2 || s1 + l == s2 + len - 1 )
            {
                /* The two objects overlap, so we're allowed to
                   use comparison operators. */
                if(s1 > s2)
                    return 1;
                else if (s1 < s2)
                    return -1;
                else
                    return 0;
            }
        }
    
        /* No overlap so the result probably won't really matter.
           Cast the result to `uintptr` and hope the compiler
           does the "usual" thing */
        if((uintptr)s1 > (uintptr)s2)
            return 1;
        else if ((uintptr)s1 < (uintptr)s2)
            return -1;
        else
            return 0;
    }
    

提交回复
热议问题