2

I am converting blocks of C code into Java, and I came across some syntax that I can not quite understand. The first one uses #define to create a function. I personally have not seen #define to create functions before. I also just found out in this post that this is really a macro. Below you will see what I attempted to interpret this code as in Java. Here is the C code:

#define mat_elem(a, y, x, n) (a + ((y) * (n) + (x)))

Which I then converted to this in Java:

public double mat_elem(double a, int y, int x, int n){
   return (a + ((y) * (n) + (x)));
}

Now the real issue here, is this block of code that also uses #define. Code in C:

#define A(y, x) (*mat_elem(a, y, x, n))

I have not converted into Java yet because I'm not too sure what is going on.

I first thought that #define A(y, x) creates a data type that is equal to whatever get's returned in (*mat_elem(a, y, x, n)). However, the pointer that they are using in front of mat_elem is throwing me off.

I was thinking of doing something like this in Java:

public double[] fillA(double y, double x){
   double [] A = new double [100];
   for(int i = 0; i < some_var; i++){
      A[i] = mat_elem(a, y, x, n);
   }
   return A;
}

I'm sure something like this would work, however my main concern is understanding what the C code is really doing, and If my imperfect code is equivalent to the code in C.

frlzjosh
  • 410
  • 5
  • 17
  • 2
    `#define` doesn't define a function, but a macro that is expanded each time where it is used. If `a` is a pointer to a matrix, it returns a pointer to an element inside the matrix. In Java, you can define the matrix as a two-dimensional array of double (`double[][]`) and (after you have properly initialised it) you won't need this `mat_elem` – Erwin Bolwidt Apr 28 '19 at 23:25
  • Hm, okay I'm not familiar with macro's but I will look into it. Can you explain what you mean by how it is expanded whenever it is used ? Are you essentially saying that a macro acts similar to a pointer with it's dynamic behaviors ? – frlzjosh Apr 28 '19 at 23:40
  • 2
    No - macros are (almost) textually replaced in the code. If the code said `A(3, 4) = 5.0;` then this is first "replaced" with `*mat_elem(a, 3, 4, n) = 5.0;` which is "replaced" with `*((a + ((3) * (n) + (4))) = 5.0;` In Java, just say `a[3][4] = 5.0;` – Erwin Bolwidt Apr 28 '19 at 23:44

2 Answers2

1

I do not like that C code much, but you work with what you got.

When you get something like this, your best bet to translating the C to the Java is to comment out the header includes and run it through the preprocessor and translate the preprocessed C code. See this answer for how to invoke the preprocessor: How do I run the GCC preprocessor to get the code after macros like #define are expanded?

In fact you only want to do this once, then work out what it's doing, and do the rest of the replacements intelligently, applying the logical meaning of the code rather than the direct meaning.

In this it expands to *(a + ((dia) * (n) + (dia)). ((dia) * (n) + (dia) is an integer, a pointer plus an integer is a pointer. Therefore, it ads this complex expression to the pointer and dereferences it. More commonly written as a[((dia) * (n) + (dia)].

Looks like the original C programmer was trying to construct a two dimensional array where the second dimension wasn't a constant. Arrays of arrays are idiomatic but this actually would be faster on most processors.

Joshua
  • 40,822
  • 8
  • 72
  • 132
  • Okay so when running it, I see that `A(x,y)` get's used in this line `max = (*(a + ((dia) * (n) + (dia))));` If I were to write in java would it be something like this: `max[i] = ((a + ((dia)* (n) + (dia)))` I am asking because seeing the pointer in there: `(*(a + ((dia) * (n) + (dia))))` still confuses me. – frlzjosh Apr 29 '19 at 01:51
  • Very interesting. I'm still struggling to see how this a 2D array. However, I now understand that `a` is being targeted as the pointer when that macro is getting executed, and how to use preprocessors in C now. – frlzjosh Apr 29 '19 at 02:19
  • Just thought of something. Is it a 2D array because `a` as a pointer will get filled in `max[i]` ? So it what I'm thinking is that it would look like this: `max[i] = *(a+((dia)*(n)+(dia))` ? – frlzjosh Apr 29 '19 at 02:21
  • 1
    @frlzjosh: The 2D array is allocated as a single D array with size `maxx * maxy` and is indexed as `a[x + y * maxy]` where `maxy` is known as `n` in the macro. – Joshua Apr 29 '19 at 02:32
1

Both mat_elem and A are what are called function-like macros.

A macro is a simple text substitution. If you define a macro like

#define FOO a + b

then when the code is run through the preprocessor, every instance of FOO in the source code is replaced with the text a + b.

Function-like macros are similar, except that you can pass arguments to be expanded as well. If you write mat_elem(my_matrix, i, j, rows), then when the code is preprocessed that will be replaced with the text

(my_matrix + ((rows) * (i) + (j))

Note that macro arguments are not evaluated like function arguments - they are simply expanded in place. mat_elem(mat, i++, j+2, rows) will expand to

(mat + ((rows) * (i++) + (j+2))

Macros can invoke other macros. A(i, j) expands to (*mat_elem(a, y, x, n)), which in turn expands to

(*(a +((n) * (y) + (x)))

There is no equivalent facility in Java AFAIK - you will have to write methods to accomplish the same thing.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • Thank you for this piece of info. Yeah, I assumed that I would need a method to accomplish this. It's because I will need to converted this into Java Code to then be able to write a Java Stream. – frlzjosh Apr 29 '19 at 04:35