Reputation: 462
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.
Upvotes: 2
Views: 630
Reputation: 123548
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.
Upvotes: 1
Reputation: 43317
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.
Upvotes: 1