C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Make all data pointers intercompatible

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Sun, 12 May 2024 23:45:03 +0100
On Thu, May 9, 2024 at 4:50 PM Thiago Macieira wrote:
>
> Right.
>
> What's the problem?


The problem is that C++ programmers today in 2024 are hindered by an
old compiler that's rumoured to have existed (which I'm beginning to
doubt ever existed at all). I don't want to hear people throwing
around words like 'exotic' -- I need a vendor name, product name and
year of release for a C++ (or even C) compiler whose char* is bigger
than its double*. Can anyone actually name a single compiler that has
sizeof(char*) > sizeof(double*)? I can't find anything from searching
the web, and ChatGPT just told me now that it doesn't know of any
either. If I ask ChatGPT to tell me about a compiler that has data
pointers a different size to code pointers, it comes back with "The
Keil C51 compiler for the Intel 8051 microcontroller" -- but it can't
give me an example of a C/C++ compiler whose char* is different in
size to any other data pointer.

So C++26 should mandate that the following code is well-formed with
well-defined behaviour:

    #include <iostream> // cout, endl

    double long *Backwards(double long *const arg)
    {
        return (double long*)((char*)arg - 1);
    }

    double long *Forwards(double long *const arg)
    {
        return (double long*)((char*)arg + 1);
    }

    int main(void)
    {
        double long d = 123.456L;
        *Backwards(Forwards(&d)) = 666.0L;
        std::cout << d << std::endl;
    }

C++26 should mandate that all data pointers are the same size with the
same representation, and it should explicitly say that it's safe to
store the address of an unaligned T inside a T*. The following should
also be OK:

    int main(void)
    {
        char c = 'a';
        *(char*)(double long*)(std::string*)(int*)&c = 'b'; // no
problems here
    }

And the Standard should also mandate that aliasing rules no longer
apply once you cast a pointer. Consider the following function:

    void Func(double *const a, int const *const b)
    {
         *a += *(double*)b;
         *a += *(double*)b;
    }

A compiler should be forbidden from optimising the above to:

    *a += *(double*)b * 2.0;

because the cast from "int*" to "double*" turns off the aliasing
rules, and so the compiler must accommodate the possibility that 'a'
and 'b' point to the same double.

Received on 2024-05-12 22:45:11