Question: ```
    typedef void* TVPtr;
    typedef const void* CTVPtr;

const TVPtr func3 (const TVPtr p)
{
    return p;
}

const void* func4 (const void* p)
{
    return p;
}

CTVPtr func5 (CTVPtr p)
{
    return p;
}

int main ()
{
    const uint64_t i = 10;

    func3(&i);  // compilation error here
                // cannot convert argument 1 from 'const uint64_t *' 
                // to 'const TVPtr' Conversion loses qualifiers    
    func4(&i);  // no compilation error
    func5(&i);  // no compilation error
    return 0;

}

```

I do not understand why there is error is one case and not in the other two?

Answer: 
`const TVPtr` is not `const void*`, it's `void* const`. In other words, it's not a pointer to `const void`, it's a `const` pointer to `void`. Since `i` is declared `const` it will happily bind to a `const void*`, but not a `void* const`, because that discards the `const`ness of the object itself.
func3 expects a non const type and promises not to change it via the const keyword preceding the type in the argument list. The others are fine with taking pointers to const types since CTVPtr is a pointer to const data.

I think the confusion came from the const key word you used which actually meant func3 will not change the data pointed by p rather than saying func3 will accept a const TVPtr.

If you really want to pass address of i to func3, you can cast it like this

```
func3( (void*)&i);

```