Regarding Unchecked_Conversion in ada - ada

Could anyone please explain me the operation of ada.unchecked_coversion(float, UnsignedInteger). What this operation will be performed ? Could anyone please clarify this with example. Thanks a lot in advance.

From here
An unchecked conversion is a bit-for-bit copy without regard to the meanings attached to those bits and bit positions by either the source or the destination type. The source bit pattern can easily be meaningless in the context of the destination type. Unchecked conversions can create values that violate type constraints on subsequent operations. Unchecked conversion of objects mismatched in size has implementation-dependent results.
So it should be used with care and only for types that have "same" bit representation. e.g it wouldn't probably work to cast float to int as those types could be represented differently in memory.
Here are two variables
A: source float designated by address 0x249fd8c with value 1.0
B: target Integer designated by address 0x249fd88 (unitialized)
before conversion
and after calling unchecked conversion
As you can see whole operation is just bit by bit copy of source variable to target variable
Hope this answers your questions

Normally an unchecked conversion has no effect at run time. It does not result in any code being generated. It is just permission to the compiler to interpret the bytes of the source value as the representation of a value of the target type. Most importantly, it does not cause a copy.

Related

What does crossbeam_epoch::Shared::as_raw mean by "Converts the pointer to a raw pointer (without the tag)"?

Can someone translate this into something that makes sense for me:
Converts the pointer to a raw pointer (without the tag).
What is the difference between a pointer and a raw pointer?
The Stack Overflow raw-pointer tag says neither "smart" nor "shared" which again is mystifying.
What are Crossbeam's Shared::as_raw's "tags" all about?
crossbeam_epoch::Shared is a smart pointer. That is, a pointer plus extra stuff. In C++ or Rust, smart pointer is the term used for a pointer wrapper which adds any of the following:
Ownership information
Lifetime information
Packing extra data in unused bits
Copy-on-write behavior
Reference counting
In that context, a raw pointer is just the wrapped pointer, without all the extra stuff.
crossbeam_epoch::Shared fits (among others) in the “Packing extra data in unused bits” category above. Most data in modern computers is aligned, that is, addresses are a multiple of some power of two. This means that all low bits of the addresses are always 0. One can use that fact to store a few extra bits of information in a pointer.
This extra data is called tag by this particular library, however that term isn't as common as raw pointer.

Ada pragma Pack or Alignment attribute for Records?

Having just discovered alignment issues for the first time I am unsure on which method is the best/safest way to deal with them. I have a record which I am serialising to send over a Stream and vice-versa so it must meet the interface spec and contain no padding.
Given the example record:
type MyRecord is record
a : Unsigned_8;
b : Unsigned_32;
end record;
This by default would require 8 bytes but I am able to remove packing using 2 methods:
for MyRecord'Alignment use 1;
or
pragma Pack (MyRecord);
I have found a few questions relating to C examples but haven't been able to find a clear answer on which method is the most appropriate, how to determine which method to use or if they are equivalent?
UPDATE
When I tried both on my 'real' code rather than a basic example I found that the Alignment attribute achieved what I was looking for. pragma Pack significantly reduced the size, not confirmed but I assume it has packed the many enumerated types I'm using, overriding the 'Size use 8 attribute applied to each type.
For Streams you could leave MyRecord without any representation clauses and use the default MyRecord’Write and MyRecord’Read; ARM 13.13.2(9) says
For elementary types, Read reads (and Write writes) the number of stream elements implied by the Stream_Size for the type T; the representation of those stream elements is implementation defined. For composite types, the Write or Read attribute for each component is called in canonical order, which is last dimension varying fastest for an array (unless the convention of the array is Fortran, in which case it is first dimension varying fastest), and positional aggregate order for a record.
One possible disadvantage of the GNAT implementation (and maybe of others) is that the ’Write and ’Read calls each end in a call to the underlying network software. Not a problem (aside from possible inefficiency) normally, but if you’re using TCP_NODELAY (or worse, UDP) this is not the behaviour you’re looking for.
Overloading ’Write leads back to your original problem (but at least it’s confined to the overloading procedure, so the rest of your program can deal with properly aligned data).
I’ve used an in-memory stream for this (especially the UDP case); ’Write to the in-memory stream, then send the Stream_Element_Array to the socket. One example is ColdFrame.Memory_Streams (.ads, .adb).
I think you want the record representation clauses, if you want full control:
for MyRecord'Size use 40;
for MyRecord use record
a at 0 range 0 .. 7;
b at 1 range 0 .. 31;
end record;
(or some such, I might have messed up some of the indices here).
NB: edited as per comment by Simon

What does that mean when we say uintptr stores the uninterpreted bits of a pointer value?

I read in golang website that uintptr stores the uninterpreted bits of a pointer value, the kind of anwsers that i found on web were very confusing.Can someone please explaing this to me in simple words .
Short answer: it's used when you need to use an address as if it's a number.
Go is a garbage-collected language. Go always knows exactly, when a thing is a pointer, and when it's just a value. Go needs this knowledge to look for old unused values that it can free. Pointers are also special in Go in that you can't just add a number to a pointer like you would do in C.
But sometimes, when you work with embedded systems or some kind of low-level libraries where you need to add or subtract from an address, you need to tell Go that it shouldn't check this pointer because it's not pointing to anything useful at the moment. You just want to use this address as if it was a number and add/subtract another number to it.
This is where you would use uintptr. This type can hold any pointer value (any address), and when you put an address into it, Go doesn't see it as a pointer, so you can do whatever you want with it.

Arithmetic operation in Assembly

I am learning assembly language. I find that arithmetic in assembly can be either signed or unsigned. Rules are different for both type of arithmetic and I find it is programmer's headache to decide which rules to apply. So a programmer should know beforehand if arithmetic involves the negative numbers or not. if yes, signed arithmetic rules should be used, else simpler and easier unsigned arithmetic will do.
Main problem I find with unsigned arithmetic is ‘what if result is larger than its storage area?’. It can be easily solved by using a bigger-than-required storage area for the data. But that will consume extra bytes and size of data segment would increase. If size of the code is no issue, can't we use this technique freely?
If you are the programmer, you are in control of your data representation within the bounds of the requirements of your software's target domain. This means you need to know well before you actually start touching code what type of data you are going to be dealing with, how it is going to be arranged (in the case of complex data types) and how it is going to be encoded (floating-point/unsigned integer/signed integer, etc.). It is "safest" to use the operations that match the type of the data you're manipulating which, if you've done your design right, you should already know.
It's not that simple. Most arithmetic operations are sign agnostic: they are neither signed nor unsigned.
The interpretation of the result—which is determined by program specification—is what makes them signed or unsigned, not the operation itself. The proper flavor of compare instructions always have to be chosen carefully.
In some CPU architectures there are distinct signed and unsigned divide instructions, but that is about as far as it goes. Most CPUs have arithmetic shift right instruction flavors which either preserve the high bit or replace it with zero: that can be used as signed and unsigned handling, respectively.

Ada array access: Pointer to a specific item within the array, the position being dynamic based on input parameters.

I'm working in Ada95, and I'm having difficulty figuring out pointers.
I have code that looks like the following:
type vector is array (1 .. 3) of integer;
type vector_access is access vector;
my_vec : vector;
procedure test is
pointer : vector_access := my_vec'access;
begin
...
end;
This fails compilation on the definition of pointer, saying
"The prefix to 'ACCESS must be either an aliased view of an object or denote a subprogram with a non-intrinsic calling convention"
If I then change the definition of the vector itself to:
my_vec : aliased vector
it now returns the compiler error:
"The expected type for X'ACCESS, where X denotes and aliased view of an object, must be a general acces type"
At the end of the day what I really need is a pointer to a specific item within the array, the position being dynamic based on input parameters. Can anyone point me in the right direction?
If you're using GNAT, the error message after the "must be a general access type" should have given you the solution:
add "all" to type "vector_access"
defined at line ...
so that you would end up with:
type Vector_Access is access all Vector;
The use of "all" to designate a general access type has to do with dynamic memory allocation pools in Ada. If you don't care about dynamic memory allocation pools, then don't worry about it, and just include "all" in your access type definitions.
I'm not sure if this is part of what you're looking for at the end of the day, but you are aware that in most circumstances Ada's access (pointer) types are used to handle dynamically allocated memory, right?
So instead of pointing my_vec at an aliased variable, you would dynamically allocate it:
Pointer_2_Dynamic : vector_access := new Vector;
This way you can dynamically allocate at runtime the objects you need, and easily handle variably sized ones (though you'd need a different vector definition to accomplish that:
type Dynamic_Vector is array (Natural range <>) of Integer;
type Dynamic_Vector_Access is access Dynamic_Vector;
N : Natural := 10; -- Variable here, but could be a subprogram parameter.
Dyn_Vector : Dynamic_Vector_Access := new Dynamic_Vector(1..N);
OK. Lesson one on Ada for expert Cish coders: Ada parameters are different than Cish parameters. In C, (pre-reference parameters) every single parameter is the equivalent of an Ada 'in' parameter, with an extra proviso that the C compiler must always stupidly pass the entire thing on the stack, no matter how huge it is. So you poor C coders get it nailed into your brains that you never pass large objects into subroutines directly, but always use pointers.
Ada is different. You tell the compiler how you want to access your parameters (read only - 'in', write only - 'out', or read write - 'in out'). However, that has nothing to do with how parameters are passed. The parameter passing mechanisim is up to the compiler, and the compiler will chose the most efficient way to do it. In practice, on nearly all platforms, that means than anything too big for a register will be passed by reference. But this is an implementation detail, and is the compiler's business, not yours. You shouldn't even have to think about it, except in really rare cases.
So grit your teeth and pass that array naked as an in out parameter. Trust me, you'll get to like it.
type vector is array (natural range <>) of integer;
my_vec : vector(1..3);
procedure test (subject : in out vector) is
begin
...
end;
Ada is designed to be quite usable in nearly all cases without needing pointers, and usable in all but a very few very rare cases without needing pointers to stack-allocated objects.
The former is fairly unsafe (dangers from unallocated pointers and memory leaks), and the latter is even more unsafe (stack objects may go out of scope before your pointer does, and even if they don't one little size error can corrupt your entire program). You can still do both in Ada, but unlike many languages it is designed to make unsafe things require a bit more work on your part to do, and make very unsafe things a major PITA to write.
For example, if you'd just dynamically allocate the entire array, you wouldn't have to fool with this aliased and all business. Furthermore, if you just want to pass the array into a subroutine, you could simply pass it as a parameter and you don't even have to fool with the dynamic allocations and deallocations. Again, Ada compilers are smart enough to pass large objects by reference (yes, even if you specified in). This takes an attitude adjustment from C/C++ coders, who are used to having to tell their dumbass compiler not to pass 10meg objects on the stack. You have to learn to let the Ada compiler worry about how to pass your parameters around efficiently, and you can just worry about how to write great code.
Think I found it, for anyone else running into the same issue.
The answer has to do with what specifically is being aliased. The array declaration needs to be:
type vector is array (1 .. 3) of aliased integer;
in order to make sure the integers are stored in memory, and not registers.

Resources