So I have a .h file defined as this
#ifndef CONSTANTS_H
#define CONSTANTS_H
#include "math.h"
//CALA = CA/LA, CRLR = CR/LR
#define CALA 0.2
#define CRLR 25.0
//self-propulsion and friction
#define ALPHA .15
#define BETA .05
//Evolution simulation size
#define STUDYSIZE 100
#define STUDYLENGTH 1
.....
#define INITIAL_CONDITION true
#endif
Is there a way to import the constants that I defined here and turn them into matlab variables.
Try this -
%%// Read in data
imp_data = importdata(CPP_H_FILE,'\n');
%%// Remove the leading and trailing whitespaces
imp_data = cellstr(strtrim(char(imp_data)));
%%// Split into strings
split1 = regexp(imp_data,'\s','Split');
%%// Process to evaluate the variables into MATLAB
for k = 1:size(split1,1)
if strcmp(char(split1{k,1}(:,1)),'#define') && numel(split1{k,1})>2
val_str = strtok(char(split1{k,1}(:,end)), '/');
evalstr = strcat(char(split1{k,1}(:,2)),'=',val_str);
evalc(evalstr);
end
end
Related
I am trying to use Boost.Preprocessor to do some compile-time work. I want to index a table using values that are computed in other macros. When I try I get the following error: "concatenation with '(' in macro 'BOOST_PP_BOOL_I' does not create a valid token."
This is the simplest code that produces the issue.
#define MY_TABLE (0, (1, BOOST_PP_NIL))
#define MY_INDEX_FUNCTION(x) (x)
void func() {
int y = BOOST_PP_LIST_AT(MY_TABLE, MY_INDEX_FUNCTION(0));
}
It is pretty easy to determine that removing the parens in MY_INDEX_FUNCTION resolves the issue in this case. My actual code uses a much more complex function to calculate the table index in a much larger table.
Is there something that I can do or change that would fix this such that the parens and more complex macros don't cause problems?
The second parameter of BOOST_PP_LIST_AT takes an index/integer. It works with tricky preprocessor hacks under the hood. The parameter(expanded) should be exactly an integer-literal, not an integer inside parenthesis. The MY_INDEX_FUNCTION should be changed, so that the parameter passed to the BOOST_PP_LIST_AT is literally an integer-literal:
#define MY_INDEX_FUNCTION(x) x
The macro does not work with arithmetic expressions, this will not work:
#define MY_INDEX_FUNCTION(x) (x+1)
NOR
#define MY_INDEX_FUNCTION(x) x+1
But you can do this with
#define MY_INDEX_FUNCTION(x) MY_INDEX_FUNCTION_ ## x
#define MY_INDEX_FUNCTION_0 1
#define MY_INDEX_FUNCTION_1 2
#define MY_INDEX_FUNCTION_2 3
//...
This macro definitions can be created by a (python-)script
def my_index_function(x):
# insert the behavior of the macro here
return x+1
MACRO_NAME = "MY_INDEX_FUNCTION"
INDEX_MAX = 255
for x in range(INDEX_MAX):
print("#define %s_%i %i" % (
MACRO_NAME,
x,
my_index_function(x),
))
print("#define %s(x) %s_ ## x" % (
MACRO_NAME,
MACRO_NAME,
))
Not sure how to word this but, Is there any way to increment a macro?
I have several offset macros, the first defined offset must be zero, the next one must be 1, and so on.
If I need to add an offset macro to the middle of the list, it can be cumbersome to increment all the offsets below it manually.
//How can I turn this...
// v This number needs to increment by 1 (no matter the order)
#define OFFSET_X 0
#define OFFSET_Y 1
#define OFFSET_Z 2
#define OFFSET_W 3
//Into something like this... (order of macros swapped yet the numbering still goes from 0 to 3)
int num = 0;
#define OFFSET_Z num++ // = 0 (was 2)
#define OFFSET_Y num++ // = 1 (was 1)
#define OFFSET_X num++ // = 2 (was 0)
#define OFFSET_W num++ // = 3 (was 3)
With the original order,
#define OFFSET_X 0
#define OFFSET_Y (OFFSET_X + 1)
#define OFFSET_Z (OFFSET_Y + 1)
#define OFFSET_W (OFFSET_Z + 1)
or with the revised order in the second part of your post,
#define OFFSET_Z 0
#define OFFSET_Y (OFFSET_Z + 1)
#define OFFSET_X (OFFSET_Y + 1)
#define OFFSET_W (OFFSET_X + 1)
etc. Since all this gets evaluated at compile time, anyway, there's no perf hit.
Or you could write a code generator, if you're really bored, and have it generate the values for you.
Or just use an enum. This is what they're for, and they're treated as constants by the compiler, anyway - but you get compile-time error checking which is far less effective with macros.
BUT, a better solution may be constexpr added in C++11.
In any case, if you only have four of these, this is overkill.
Just use an enum:
enum class offsets {
X = 0,
Y = 1,
Z = 2,
W = 3
};
and don't sweat it. Want auto-increments? Even easier:
enum class offsets { X = 0, y, z, w };
for the same effect.
Note I've suggested an enum class, so the usage is offsets::X, offsets::Y etc.
In some cases you may prefer an constexpr std::array, which you could then iterate over (something you can't do with macros or enums).
#include <iostream>
using namespace std;
#ifndef R
#define N1 10
#ifndef R
#define N2 11
#endif
#endif
int main(){
cout << N2 << endl;
}
From my understanding if R is not defined then N1 will be 10.
And second case where again R is defined again it should not be able to define N2 as 11, because R is already defined. I am just confused about it, And one Can please help to understand the point I have missed.
Let's walk through the code:
#ifndef R
R hasn't been defined yet, so step into the branch:
#define N1 10
N1 becomes 10
#ifndef R
R still hasn't been defined yet, so step into nested branch
#define N2 11
N2 is assigned to 11
#endif
Ends the nested branch
#endif
Ends the primary branch
So in the end R was never defined, so we assign N2 successfully.
You need to explicitly #define R or use -DR in the compiler line to define R, it won't get defined for you within a ifndef R branch.
The second #ifndef is redundant the way you currently have it organized. I'll write this out in a clearer pseudo code
IF R IS NOT DEFINED
SET N1 = 10
IF R IS NOT DEFINED
SET N2 = 11
END IF
END IF
This can be more simply
IF R IS NOT DEFINED
SET N1 = 10
SET N2 = 11
END IF
or in C/C++ preprocessor notation
#ifndef R
#define N1 10
#define N2 11
#endif
#define N 1
#define A(N) #N
#define S_A A(N)
#define B_(N) #N
#define B(N) B_(N)
#define S_B B(N)
#include <stdio.h>
int main(void) {
puts(S_A);
puts(S_B);
}
outputs N and 1 instead of two 1s.
Why is the extra indirection making a difference?
It works different because the macro expansion of N only happens on the "use" of N. So S_A exands to A(N), which is expanded to #N. In S_B it is expanded to B(N), which is expanded to _B(1), and then #1. Why? Well, how would you do something like:
#define COMBINE(A, B) A##B
#define foo 1
#define bar 2
int COMBINE(foo, bar) = 34;
so that it generates int foobar = 34;, and not the illegal int 12 = 34;.
Did you intend to use a ## operator for token pasting?
puts(S_A); //Gets expanded into puts(A(N)) --> puts(#N)
and
puts(S_B); //Gets expanded into puts(B(N)) --> puts(_B(1)) --> puts(#1)
Without affecting your macros much, if you intend to print 1,1 both the times, you could Use the macros this way:
#define N "1" //instead of 1
#define A(N) N //instead of #N
#define B_(N) N //instead of #N
I have the source code of an application written in C++ and I just want to comment something using:
#ifdef 0
...
#endif
And I get this error
error: macro names must be identifiers
Why is this happening?
The #ifdef directive is used to check if a preprocessor symbol is defined. The standard (C11 6.4.2 Identifiers) mandates that identifiers must not start with a digit:
identifier:
identifier-nondigit
identifier identifier-nondigit
identifier digit
identifier-nondigit:
nondigit
universal-character-name
other implementation-defined characters>
nondigit: one of
_ a b c d e f g h i j k l m
n o p q r s t u v w x y z
A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z
digit: one of
0 1 2 3 4 5 6 7 8 9
The correct form for using the pre-processor to block out code is:
#if 0
: : :
#endif
You can also use:
#ifdef NO_CHANCE_THAT_THIS_SYMBOL_WILL_EVER_EXIST
: : :
#endif
but you need to be confident that the symbols will not be inadvertently set by code other than your own. In other words, don't use something like NOTUSED or DONOTCOMPILE which others may also use. To be safe, the #if option should be preferred.
Use the following to evaluate an expression (constant 0 evaluates to false).
#if 0
...
#endif
This error can also occur if you are not following the marco rules
Like
#define 1K 1024 // Macro rules must be identifiers error occurs
Reason: Macro Should begin with a letter, not a number
Change to
#define ONE_KILOBYTE 1024 // This resolves
#ifdef 0
...
#endif
#ifdef expect a macro rather than expression
when using constant or expression
#if 0
...
#endif
or
#if !defined(PP_CHECK) || defined(PP_CHECK_OTHER)
..
#endif
if #ifdef is used the it reports this error
#ifdef !defined(PP_CHECK) || defined(PP_CHECK_OTHER)
..
#endif
Where #ifdef expect a macro rather than macro expresssion
Note that you can also hit this error if you accidentally type:
#define <stdio.h>
...instead of...
#include <stdio.>