0

Consider the following simple function in c++...

int function(int *a, int x)
{
     return x*x;
}

My question is: How to translate the above function into an ada function as I can't write the pointer.

Thanks in advance

  • Do you want to write the equivalent Ada subprogram, or do you want to call the C function from Ada? And what do you want `a` to do (I ask because your example doesn’t actually use it). You might be going to save the pointer for later use, or you might want to update the current value of `*a`; in which case, do you care what the previous value was? – Simon Wright Mar 28 '14 at 21:07
  • Please do not change the titles of posts like you did. This is not a forum. With a title like that - how will anyone know what the content of the post really is? – Lix Mar 30 '14 at 16:14
  • To mark a post as "solved" as you are implying, all you have to do is mark an answer as accepted. As you can see, a green checkmark appears and *this* is what indicates that a post has been answered. – Lix Mar 30 '14 at 16:15
  • @Lix sorry I didnot know –  Mar 30 '14 at 16:16
  • @user3459170 - no worries! Now you know :) I've taken the liberty of reverting the changes you made to your other questions too. – Lix Mar 30 '14 at 16:16

3 Answers3

3

You can pass pointers (access types) into Ada functions or procedures but you normally don't want to.

The usual reason for passing a pointer into a C function is to allow the function to modify the thing pointed at.

C doesn't have any better way of letting you do that; Ada does.

Instead of passing values or pointers (or in C++, references), you pass objects with appropriate modes : In, Out, In Out, describing how the argument is used.

  • In : the argument is only an input and can't be modified. (This is the default; without specifying a Mode you get mode In.
  • Out : the argument is an output (to a procedure : functions shouldn't have Out parameters, but Ada-2012 relaxes this rule) and the procedure will update the value in the argument.
  • In Out : not surprisingly, both an input and an output.

So you probably want to write

function My_Func (a : in out Integer;
                  x : in     Integer) return integer is
begin
   return x * x;
end My_Func;

but there are several problems:

  1. You can't name it "function" because that's a reserved word
  2. The unused argument is an error
  3. (until Ada-2012) you can't have an out or in out argument from a function; they are reserved for procedures (which C would call "void functions")

The last one may look odd : Ada's functions are ideally functions in the mathematical sense, not the C sense of being "any old subprogram". That is, they accept arguments, process them without modifying them or anything else and return a result. These are called pure functions and like proper operators you can optimise around them much more safely than is otherwise true.

Ada unlike some stricter languages, does allow impure functions which may modify state (e.g. updating the seed in a random generator on each call) and as of 2012 also allows out and in out parameters; a legitimate use would be to update an "OK" flag in a series of operations like file reads.

So how do we normally use Out parameters? In a procedure, which like a statement, can modify things (assignment) or change state. So if you meant to use the argument a you might write:

procedure My_Proc (a :    out Integer;
                   x : in     Integer) is
begin
   a := x * x;
end My_Proc;

Think of a function as an abstraction over an expression, while a procedure abstracts over a statement. (This leads to some obvious refactorings; replace expression with function, statement or block with procedure).

If this doesn't actually answer the question and you think you might really need pointers, add a comment or update the question.

Community
  • 1
  • 1
  • Typo: Ada uses `;`, not `,`, to separate parameters in declarations. – ajb Mar 29 '14 at 00:29
  • Mr. Brian, I'm just trying to convert a heap sorting algorithm I created in c++ into ada. The problem I faced is that I needed to pass by reference the array created inside the main to other procedures... but I couldn't manage to make those procedures accept a reference to an array as an argument. In c++, even something in the parameters like `int *a` would accept the array. So please tell me how to do this in ada. Thanks in advance :) –  Mar 29 '14 at 07:35
  • @ajb : thanks for correction; I should have compiled it! –  Mar 29 '14 at 10:40
  • @user3459170 : just pass the array as mode `in out` as Simon says. No pointers! –  Mar 29 '14 at 10:42
1

Further to Brian’s answer, you might declare

type Arr is array (Integer range <>) of Integer;

(that’s to say, all instances of Arr are arrays containing Integers indexed by Integers, but different instances can have different bounds). There are three common ways of writing subprograms that use Arrs.

If you only want to read the values, use (or default to) in mode:

function Sum (A : Arr) return Integer
is
   Total : Integer := 0;
begin
   for J in A'Range loop
      Total := Total + A (J);
   end loop;
   return Total;
end Sum;

If you don’t care what the previous contents were, use out mode:

procedure Initialize (A : out Arr; To : Integer)
is
begin
   for J in A'Range loop
      A (J) := To;
   end loop;
end Initialize;

If you want to update the previous contents, use in out mode:

procedure Multiply (A : in out Arr; By : Integer)
is
begin
   for J in A'Range loop
      A (J) := A (J) * By;
   end loop;
end Multiply;

Sticking to Ada 2005, functions aren’t allowed to have out or in out parameters, but (as NWS said) you can use access mode:

function Divide_And_Sum (A : access Arr; By : Integer) return Integer
is
   Sum : Integer := 0;
begin
   for J in A'Range loop
      A (J) := A (J) / By;
      Sum := Sum + A (J);
   end loop;
   return Sum;
end Divide_And_Sum;

but then you need to declare the actual array aliased:

T : aliased Arr := (0, 1, 2, 3, 4, 5);

and pass its ’Access in the call:

New_Sum := Divide_And_Sum (T'Access, 2);
Simon Wright
  • 25,108
  • 2
  • 35
  • 62
0

In Ada, Pointers are not implicitly defined (by using a *), you need to define their types explicitly like below:

   type Int_Ptr is access Integer;

   function My_Func (A : in Int_Ptr; 
                     X : in integer) return Integer is 
   begin
      return X*X;
   end My_Func;

Then you can produce a function exactly like the C++ one you supplied. How this helps your problem im not sure. @Brian Drummond has a useful discussion of this in his answer.

NWS
  • 3,080
  • 1
  • 19
  • 34