Home > database >  NULL behaviour on MSVC
NULL behaviour on MSVC

Time:10-21

I was trying this code snippet

#include <cstddef>
#include <cstdio>

void f(int* ptr){
    std::printf("int*\n");
}

void f(int val){
    std::printf("int\n");
}

int main() {
    f(NULL);
}

This errors out on both GCC and CLANG but MSVC prints int. As per my reading of [conv.ptr], since a null pointer constant (which is what NULL is) of integral type can be converted to a pointer type, it should be ambiguous for the compiler while selecting the appropriate function since it can bind both to int and int*. I confirmed that all these compilers have NULL implemented as an integral type via

#if defined(_MSC_VER)
    static_assert(std::is_same<decltype(NULL), int>(), "");
#else
    static_assert(std::is_same<decltype(NULL), long>(), "");
#endif

So, is this an MSVC bug or am I missing something and compilers are not expected to throw an error in such cases?

EDIT: I'm aware that nullptr is the way to gauge null-ness, but this question is merely out of curiosity and an attempt at understanding the specification around it.

CodePudding user response:

NULL is an old C-compatibility macro. It's usually defined as the plain integer 0. Because of that f(int) will be called.

In C you should be using nullptr for null pointers.

CodePudding user response:

since a null pointer constant (which is what NULL is) of integral type can be converted to a pointer type, it should be ambiguous for the compiler while selecting the appropriate function since it can bind both to int and int*.

It's only ambiguous when the overload resolution has to choose between two equivalent conversion sequences. E.g. from 0L to int or int*.

But overload resolution is trivial when one of the overloads is a perfect match. And as it happens, 0 is a perfect match for int.

Both 0 and 0L have integral type, so all compilers are correct.

Bonus:

void f(std::integral auto val) {
    std::printf("integral\n");
}

Perfect match after template instantiation.

  • Related