Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

strange error (QT Creator 4.12.2, based on QT creator 5.14.2)

33 views
Skip to first unread message

MarioCPPP

unread,
Mar 2, 2023, 11:25:30 AM3/2/23
to

I have this situation :

int32_t * Pointer32; // is a 4 byte signed int
int8_t * Pointer8; // is a "signed char"
// pointer allegedly "unaligned".

Pointer32 = new int32_t [10];
// supposedly ALIGNED a multiple of four byte addresses

Pointer8 = static_cast <int8_t *> (Pointer32);

ERROR : STATIC CAST FROM int * to signed char * IS NOT ALLOWED.

I am asking why that ?

I mean, the reverse, maybe with a warning, seems weird (at
best very slow).

But casting a MORE RESTRICTIVELY ALIGNED pointer to one LESS
RESTRICTIVELY ALIGNED seems pretty reasonable. Why not ?

how comes I cannot access single bytes aligned whatever in
an int array ?
The type does not even have "NAN" problem or the drawback
i.g. of creating underflows, overflows, denormalized values
that can happen accessing FLOAT / DOUBLE on a random address
bytewise mode.

But integral types SHOULD be accessible byte by byte without
problems, and a single byte does not have alignment
restrictions ... I am at a loss !
help :D

--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
MarioCPPP

MarioCPPP

unread,
Mar 2, 2023, 11:27:54 AM3/2/23
to
On 02/03/23 17:25, MarioCPPP wrote:
>
> I have this situation :
>
> int32_t * Pointer32; // is a 4 byte signed int
> int8_t * Pointer8; // is a "signed char"
> // pointer allegedly "unaligned".
>
> Pointer32 = new int32_t [10];
> // supposedly ALIGNED a multiple of four byte addresses
>
> Pointer8 = static_cast <int8_t *> (Pointer32);

Using an old style casts deserves just a warning ...
Pointer8 = (int8_t *) (Pointer32);

but it seems an ugly solution for a problem still not
understood, so please explain me the "ratio" of the error
with static_cast

Bo Persson

unread,
Mar 2, 2023, 11:44:17 AM3/2/23
to
On 2023-03-02 at 17:27, MarioCPPP wrote:
> On 02/03/23 17:25, MarioCPPP wrote:
>>
>> I have this situation :
>>
>> int32_t * Pointer32; // is a 4 byte signed int
>> int8_t * Pointer8; // is a "signed char"
>> // pointer allegedly "unaligned".
>>
>> Pointer32 = new int32_t [10];
>> // supposedly ALIGNED a multiple of four byte addresses
>>
>> Pointer8 = static_cast <int8_t *> (Pointer32);
>
> Using an old style casts deserves just a warning ...
> Pointer8 = (int8_t *) (Pointer32);
>
> but it seems an ugly solution for a problem still not understood, so
> please explain me the "ratio" of the error with static_cast
>

The problem isn't about alignment, but that the code uses a pointer to
signed char. The standard allows inspecting bytes as unsigned char, but
has no special allowance for signed char.

Andrey Tarasevich

unread,
Mar 2, 2023, 12:44:32 PM3/2/23
to
On 03/02/23 8:25 AM, MarioCPPP wrote:
>
> I have this situation :
>
> int32_t * Pointer32; // is a 4 byte signed int
> int8_t * Pointer8; // is a "signed char"
> // pointer allegedly "unaligned".
>
> Pointer32 = new int32_t [10];
> // supposedly ALIGNED a multiple of four byte addresses
>
> Pointer8 = static_cast <int8_t *> (Pointer32);
>
> ERROR : STATIC CAST FROM int * to signed char * IS NOT ALLOWED.
>
> I am asking why that ?
>
> I mean, the reverse, maybe with a warning, seems weird (at best very slow).
>
> But casting a MORE RESTRICTIVELY ALIGNED pointer to one LESS
> RESTRICTIVELY ALIGNED seems pretty reasonable. Why not ?

"Aligned"? Why are you even mentioning alignment in this context? What
does it have to do with anything?

C++ is a strictly typed language and `int8_t *` and `int32_t *` are
simply two unrelated pointer types. For `static_cast` that's the end of
the line.

You wanna transgress to lower level representations and re-interpret
`int32_t` object representation as a sequence of bytes? That's what
`reinterpret_cast` is for. And that's where the matters of alignment
begin to kick in.

--
Best regards,
Andrey

MarioCPPP

unread,
Mar 2, 2023, 5:39:39 PM3/2/23
to
On 02/03/23 18:44, Andrey Tarasevich wrote:
> On 03/02/23 8:25 AM, MarioCPPP wrote:
>>
>> I have this situation :
>>
>> int32_t * Pointer32; // is a 4 byte signed int
>> int8_t * Pointer8; // is a "signed char"
>> // pointer allegedly "unaligned".
>>
>> Pointer32 = new int32_t [10];
>> // supposedly ALIGNED a multiple of four byte addresses
>>
>> Pointer8 = static_cast <int8_t *> (Pointer32);
>>
>> ERROR : STATIC CAST FROM int * to signed char * IS NOT
>> ALLOWED.
>>
>> I am asking why that ?
>>
>> I mean, the reverse, maybe with a warning, seems weird (at
>> best very slow).
>>
>> But casting a MORE RESTRICTIVELY ALIGNED pointer to one
>> LESS RESTRICTIVELY ALIGNED seems pretty reasonable. Why not ?
>
> "Aligned"? Why are you even mentioning alignment in this
> context? What does it have to do with anything?

because pointers should grant that pointed integral types
pointed are accessible at correct memory addresses ... Am I
wrong ?

I knew that "short" are aligned at addresses multiple of 2,
"int" are aligned at addresses multiple of 4, "long" are
aligned at addresses multiple of 8 bytes.
And the pointers should grant that
Pointer [Offset] can be read/written from ram with just ONE
SINGLE access and no masking of data.


>
> C++ is a strictly typed language and `int8_t *` and `int32_t
> *` are simply two unrelated pointer types.

unrelated, and in fact the pointed types HAVE different
requisites of alignment.
But I expected casting from the MORE restrictive to the LESS
one, would not give problems.

> For `static_cast`
> that's the end of the line.
>
> You wanna transgress to lower level representations and
> re-interpret `int32_t` object representation as a sequence
> of bytes? That's what `reinterpret_cast` is for. And that's
> where the matters of alignment begin to kick in.

intresting, I will study this keyword, thank

Keith Thompson

unread,
Mar 2, 2023, 8:03:32 PM3/2/23
to
MarioCPPP <NoliMihiFran...@libero.it> writes:
> On 02/03/23 18:44, Andrey Tarasevich wrote:
>> On 03/02/23 8:25 AM, MarioCPPP wrote:
>>>
>>> I have this situation :
>>>
>>> int32_t * Pointer32; // is a 4 byte signed int
>>> int8_t * Pointer8; // is a "signed char"
>>> // pointer allegedly "unaligned".
>>>
>>> Pointer32 = new int32_t [10];
>>> // supposedly ALIGNED a multiple of four byte addresses
>>>
>>> Pointer8 = static_cast <int8_t *> (Pointer32);
>>>
>>> ERROR : STATIC CAST FROM int * to signed char * IS NOT ALLOWED.
>>>
>>> I am asking why that ?
>>>
>>> I mean, the reverse, maybe with a warning, seems weird (at best
>>> very slow).
>>>
>>> But casting a MORE RESTRICTIVELY ALIGNED pointer to one LESS
>>> RESTRICTIVELY ALIGNED seems pretty reasonable. Why not ?
>> "Aligned"? Why are you even mentioning alignment in this
>> context? What does it have to do with anything?
>
> because pointers should grant that pointed integral types pointed are
> accessible at correct memory addresses ... Am I wrong ?

What you appear to be wrong about is what "static_cast" means.

cppreference.com is not definitive, but it tends to be pretty good.

https://en.cppreference.com/w/cpp/language/static_cast

> I knew that "short" are aligned at addresses multiple of 2, "int" are
> aligned at addresses multiple of 4, "long" are aligned at addresses
> multiple of 8 bytes.

If you mean that you know that's the case for the implementation you're
using, that's fine. If you mean that it's true in general, it isn't.
Different implementations can and do have different sizes and alignments
for integer types.

[...]

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */

MarioCPPP

unread,
Mar 3, 2023, 7:22:37 AM3/3/23
to
On 03/03/23 02:03, Keith Thompson wrote:
> MarioCPPP <NoliMihiFran...@libero.it> writes:
>> On 02/03/23 18:44, Andrey Tarasevich wrote:
>>> On 03/02/23 8:25 AM, MarioCPPP wrote:
>>>>
>>>> I have this situation :
>>>>
>>>> int32_t * Pointer32; // is a 4 byte signed int
>>>> int8_t * Pointer8; // is a "signed char"
>>>> // pointer allegedly "unaligned".
>>>>
>>>> Pointer32 = new int32_t [10];
>>>> // supposedly ALIGNED a multiple of four byte addresses
>>>>
>>>> Pointer8 = static_cast <int8_t *> (Pointer32);
>>>>
>>>> ERROR : STATIC CAST FROM int * to signed char * IS NOT ALLOWED.
>>>>
>>>> I am asking why that ?
>>>>
>>>> I mean, the reverse, maybe with a warning, seems weird (at best
>>>> very slow).
>>>>
>>>> But casting a MORE RESTRICTIVELY ALIGNED pointer to one LESS
>>>> RESTRICTIVELY ALIGNED seems pretty reasonable. Why not ?
>>> "Aligned"? Why are you even mentioning alignment in this
>>> context? What does it have to do with anything?
>>
>> because pointers should grant that pointed integral types pointed are
>> accessible at correct memory addresses ... Am I wrong ?
>
> What you appear to be wrong about is what "static_cast" means.
>
> cppreference.com is not definitive, but it tends to be pretty good.
>
> https://en.cppreference.com/w/cpp/language/static_cast

I'll follow your advice and restudy this keyword.
Simply put I just believed that it was a cast made at
compile time plus some "checks" it was a legit cast. But
maybe this is wrong and I will restudy it !
Reinterpret_cast was new to me so I have to start from zero.
Tnx

>
>> I knew that "short" are aligned at addresses multiple of 2, "int" are
>> aligned at addresses multiple of 4, "long" are aligned at addresses
>> multiple of 8 bytes.
>
> If you mean that you know that's the case for the implementation you're
> using, that's fine. If you mean that it's true in general, it isn't.
> Different implementations can and do have different sizes and alignments
> for integer types.

it is true for types used by QTcreator that has "explicit"
fixed byte-width types for 1,2,4,8 bytes.
They are likely some typedefs defined in math.h

>
> [...]

Keith Thompson

unread,
Mar 3, 2023, 12:30:02 PM3/3/23
to
MarioCPPP <NoliMihiFran...@libero.it> writes:
> On 03/03/23 02:03, Keith Thompson wrote:
>> MarioCPPP <NoliMihiFran...@libero.it> writes:
[...]
>>> I knew that "short" are aligned at addresses multiple of 2, "int" are
>>> aligned at addresses multiple of 4, "long" are aligned at addresses
>>> multiple of 8 bytes.
>> If you mean that you know that's the case for the implementation
>> you're
>> using, that's fine. If you mean that it's true in general, it isn't.
>> Different implementations can and do have different sizes and alignments
>> for integer types.
>
> it is true for types used by QTcreator that has "explicit" fixed
> byte-width types for 1,2,4,8 bytes.
> They are likely some typedefs defined in math.h

Not in <math.h>.

The code you posted above uses int32_t and int8_t which are defined in
<cstdint> / <stdint.h>. Their sizes and ranges are guaranteed by the
C++ language definition (by reference to the C standard). Their
alignments are not.

Qt has similar typedefs qintN and quintN, for N = 8, 16, 32, 64.
The Qt project was started in 1991, before <cstdint> / <stdint.h>
was available. Presumably if Qt were being created from scratch now,
it would just use the standard types.

A N-byte integer type often requires N-byte alignment, but it's not
required. For example, 32-bit x86 systems typically use 4-byte
alignment for 8-byte integers. For most purposes, you as a programmer
don't need to know the alignment requirements for integer types; just
let the compiler take care of it.

MarioCPPP

unread,
Mar 4, 2023, 4:53:52 PM3/4/23
to
the same should hold true when you manually cast pointers to
and fro different types ?
Maybe yes, I dunno, in the doubt I thought aligning to the
most restrictive would have been prudent.

But I had chosen the wrong command (static_cast, which does
more than I supposed, and I replaced it with reinterpret_cast)

> just
> let the compiler take care of it.
>

--

Tim Rentsch

unread,
Mar 5, 2023, 11:20:42 AM3/5/23
to
This comment is at best misleading. A static_cast to (unsigned char *)
isn't allowed any more than a static_cast to (int8_t *) is.
0 new messages