Array declaration inside struct using predefined constant in C++ - c++

I want to declare an array inside a structure with a predefined constant size, but it gives me this error : expected a ']'.
#define MAX_SZAMJEGY 200;
struct szam {
int szj[MAX_SZAMJEGY];
bool negative;
};

Macro expands to
int szj[200;];
which is not valid C++ code.
remove ; from #define MAX_SZAMJEGY 200;

A preferred C++ solution is to use constants rather than macros. This way you will not have a semicolon problem, and it comes with tons of other benefits as well. Here is how:
(C++ 98):
static const size_t MAX_SZAMJEGY 200;
struct szam {
int szj[MAX_SZAMJEGY];
bool negative;
};
(C++11)
static constexpr size_t MAX_SZAMJEGY=200;
struct szam {
int szj[MAX_SZAMJEGY];
bool negative;
};
And while you are on it, and if you are using C++11, you might as well replace C-style array with C++ std::array. While it doesn't make too much of a difference, it is slightly more convenient to use.

try
#define MAX_SZAMJEGY 200
instead of
#define MAX_SZAMJEGY 200;
(the semicolon enters the macro)

Related

Using Enum to store numerical constants

I recently came across code which was similar to the following:
#include <stdio.h>
class Example {
private:
enum {
BufSize = 4096,
MsgSize = 200 * 1024,
HeaderFieldLen = 16
};
public:
int getBufSize() {
return BufSize;
}
};
int main() {
Example ex;
printf("%d\n", ex.getBufSize());
return 0;
}
A class was essentially storing constants in an enum and using their values in its member functions.
Is this a valid use of an enum and if so, is there any reason to store constants in this way, as opposed to in a struct or as regular const class member variables?
There are several ways of naming numerical constants in order to avoid magic numbers. Using enumerators are one of them.
The advantage of this method over regular const variables is that enumerators are not variables. Therefore, they are not stored as variables during run-time, they are simply used by the compiler, at compile-time.
[from the comments]
So this usage would be in some ways similar to using preprocessor macros to define constants?
The downside of macros is (mainly) type safety. Macros have no type, so the compiler cannot check for you whether the types match where you use them. Also, while macros are used in C, they are very rarely used in C++ because we have better tools at our disposal.
In C++11, a better way to name these constants is to use constexpr members.
constexpr int BufSize = 4096;
constexpr int MsgSize = 200 * 1024;
constexpr int HeaderFieldLen = 16;
The above code replaces the following.
enum {
BufSize = 4096,
MsgSize = 200 * 1024,
HeaderFieldLen = 16
};
It's valid.
In the early days, not all compilers support static const data member very well. So you have to use this enum hack to simulate a static const integer data member.
Now, since compilers have supported static const data member very well, you don't have use this hack.
// in example.h
class Example {
static const int BufSize = 4096;
};
// in example.cpp
const int Example::BufSize; // definition

Trouble declaring an array using symbolic constant

This code will not compile:
#ifndef RemoteControl_h
#define RemoteControl_h
#include "Arduino.h"
class RemoteControl
{
public:
RemoteControl();
~RemoteControl();
static void prev_track();
static void next_track();
static void play_pause_track();
static void mute();
static void vol_up();
static void vol_down();
void respond(int code);
void add_code(int code, void (*func)());
private:
boolean active = true;
struct pair {
int _code;
void (*_func)();
};
const int max = 1000;
int database_length = 0;
pair database[max]; //This line doesn't compile unless I use a literal constant instead of "max"
};
#endif
But if I put the section below in the constructor for the class instead it works fine.
const int max = 1000;
int database_length = 0;
pair database[max];
Am I not allowed to declare an array within a class in c++ and use a virtual constant as the length? I am working in arduino if that makes a difference, but I expect that I am not understanding something with the c++ language since this is a standard .h file. Oh and the problem isn't the .cpp file because I completely removed it with the same results: compiles with literal constant length but not virtual constant length.
In C or C++,try using malloc() in stdlib.h, cstdlib for c++. Don't forget free()
const int max = 1000;
struct pair *ptr = malloc(sizeof(pair) * max); // allocated 1000 pairs
free(ptr); // when the amount of memory is not needed anymore
Let me first clear a few things up for you.
In C, a const variable is considered as const-qualified, it is not a compile-time constant value (unlike an integer literal, which is a compile time constant value). So, as per the rules for normal array size specification, you cannot even use a const variable in this case.
In C, we may have the provision to use VLA which enables us to use syntax like pair database[max] even if max is not a const variable but that is again some optional feature of the compiler (as per C11).
In C++, we can use a const variable as the size of array, as in C++, a const variable is a compile time constant.
So, to answer your question:
In C, your code will be ok if your compiler supports VLA. and even if max is not const.
In C++, there is no VLA, but it maybe supported as a gnu extension. If max is const, it will be ok.
The easiest fix is to just take the
const int max = 1000;
out of the class and put it above the class.
Even better would be to ensure that it is a compile-time constant like so:
constexpr int max = 1000;

How do I use member functions of constant arrays in C++?

Here is a simplified version of what I have (not working):
prog.h:
...
const string c_strExample1 = "ex1";
const string c_strExample2 = "ex2";
const string c_astrExamples[] = {c_strExample1, c_strExample2};
...
prog.cpp:
...
int main()
{
int nLength = c_astrExamples.length();
for (int i = 0; i < nLength; i++)
cout << c_astrExamples[i] << "\n";
return 0;
}
...
When I try to build, I get the following error:
error C2228: left of '.length' must have class/struct/union
The error occurs only when I try to use member functions of the c_astrExamples.
If I replace "c_astrExamples.length()" with the number 2, everything appears to work correctly.
I am able to use the member functions of c_strExample1 and c_strExample2, so I think the behavior arises out of some difference between my use of strings vs arrays of strings.
Is my initialization in prog.h wrong? Do I need something special in prog.cpp?
Arrays in C++ don't have member functions. You should use a collection like vector<string> if you want an object, or compute the length like this:
int nLength = sizeof(c_astrExamples)/sizeof(c_astrExamples[0]);
Just use STL vector of strings instead of array:
#include <string>
#include <vector>
using namespace std;
const string c_strExample1 = "ex1";
const string c_strExample2 = "ex2";
vector<string> c_astrExamples;
c_astrExamples.push_back(c_strExample1);
c_astrExamples.push_back(c_strExample2);
int main()
{
int nLength = c_astrExamples.size();
Arrays in C++ are inherited from C, which wasn't object-oriented. So they aren't objects and don't have member functions. (In that they behave like int, float and the other built-in types.) From that ancestry stem more problems with array, like the fact that they easily (e.g., when passed into a function) decay into a pointer to the first element with no size information left.
The usual advice is to use std::vector instead, which is a dynamically resizable array. However, if you the array size is known at compile-time and you need a constant, then boost's array type (boost::array, if your compiler supports the TR1 standard extensions also available as std::tr1::array, to become std::array in the next version of the C++ standard) is what you want.
Edit 1:
A safe way to get the length of an array in C++ involves an incredible combination of templates, function pointers and even a macro thrown into the mix:
template <typename T, std::size_t N>
char (&array_size_helper(T (&)[N]))[N];
#define ARRAY_SIZE(Array_) (sizeof( array_size_helper(Array_) ))
If you (like me) think this is hilarious, look at boost::array.
Edit 2:
As dribeas said in a comment, if you don't need a compile-time constant, this
template <typename T, std::size_t N>
inline std::size_t array_size(T(&)[N])
{return N;}
is sufficient (and much easier to read and understand).
c_astrExamples is an array, there is no "length()" method in it.
In C++ arrays are not objects and have no methods on it. If you need to get the length of the array you could use the following macro
#define COUNTOF( array ) ( sizeof( array )/sizeof( array[0] ) )
int nLength = COUNTOF(c_astrExamples);
Also, beware of initialisation in a header file. You risk offending the linker.
You should have:
prog.h:
extern const string c_strExample1;
extern const string c_strExample2;
extern const string c_astrExamples[];

What is a common C/C++ macro to determine the size of a structure member?

In C/C++, how do I determine the size of the member variable to a structure without needing to define a dummy variable of that structure type? Here's an example of how to do it wrong, but shows the intent:
typedef struct myStruct {
int x[10];
int y;
} myStruct_t;
const size_t sizeof_MyStruct_x = sizeof(myStruct_t.x); // error
For reference, this should be how to find the size of 'x' if you first define a dummy variable:
myStruct_t dummyStructVar;
const size_t sizeof_MyStruct_x = sizeof(dummyStructVar.x);
However, I'm hoping to avoid having to create a dummy variable just to get the size of 'x'. I think there's a clever way to recast 0 as a myStruct_t to help find the size of member variable 'x', but it's been long enough that I've forgotten the details, and can't seem to get a good Google search on this. Do you know?
Thanks!
In C++ (which is what the tags say), your "dummy variable" code can be replaced with:
sizeof myStruct_t().x;
No myStruct_t object will be created: the compiler only works out the static type of sizeof's operand, it doesn't execute the expression.
This works in C, and in C++ is better because it also works for classes without an accessible no-args constructor:
sizeof ((myStruct_t *)0)->x
I'm using following macro:
#include <iostream>
#define DIM_FIELD(struct_type, field) (sizeof( ((struct_type*)0)->field ))
int main()
{
struct ABC
{
int a;
char b;
double c;
};
std::cout << "ABC::a=" << DIM_FIELD(ABC, a)
<< " ABC::c=" << DIM_FIELD(ABC, c) << std::endl;
return 0;
}
Trick is treating 0 as pointer to your struct. This is resolved at compile time so it safe.
You can easily do
sizeof(myStruct().x)
As sizeof parameter is never executed, you'll not really create that object.
Any of these should work:
sizeof(myStruct_t().x;);
or
myStruct_t *tempPtr = NULL;
sizeof(tempPtr->x)
or
sizeof(((myStruct_t *)NULL)->x);
Because sizeof is evaluated at compile-time, not run-time, you won't have a problem dereferencing a NULL pointer.
In C++11, this can be done with sizeof(myStruct_t::x). C++11 also adds std::declval, which can be used for this (among other things):
#include <utility>
typedef struct myStruct {
int x[10];
int y;
} myStruct_t;
const std::size_t sizeof_MyStruct_x_normal = sizeof(myStruct_t::x);
const std::size_t sizeof_MyStruct_x_declval = sizeof(std::declval<myStruct_t>().x);
From my utility macros header:
#define FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
invoked like so:
FIELD_SIZE(myStruct_t, x);

Template Metaprogramming - Difference Between Using Enum Hack and Static Const

I'm wondering what the difference is between using a static const and an enum hack when using template metaprogramming techniques.
EX: (Fibonacci via TMP)
template< int n > struct TMPFib {
static const int val =
TMPFib< n-1 >::val + TMPFib< n-2 >::val;
};
template<> struct TMPFib< 1 > {
static const int val = 1;
};
template<> struct TMPFib< 0 > {
static const int val = 0;
};
vs.
template< int n > struct TMPFib {
enum {
val = TMPFib< n-1 >::val + TMPFib< n-2 >::val
};
};
template<> struct TMPFib< 1 > {
enum { val = 1 };
};
template<> struct TMPFib< 0 > {
enum { val = 0 };
};
Why use one over the other? I've read that the enum hack was used before static const was supported inside classes, but why use it now?
Enums aren't lvals, static member values are and if passed by reference the template will be instanciated:
void f(const int&);
f(TMPFib<1>::value);
If you want to do pure compile time calculations etc. this is an undesired side-effect.
The main historic difference is that enums also work for compilers where in-class-initialization of member values is not supported, this should be fixed in most compilers now.
There may also be differences in compilation speed between enum and static consts.
There are some details in the boost coding guidelines and an older thread in the boost archives regarding the subject.
For some the former one may seem less of a hack, and more natural. Also it has memory allocated for itself if you use the class, so you can for example take the address of val.
The latter is better supported by some older compilers.
On the flip side to #Georg's answer, when a structure that contains a static const variable is defined in a specialized template, it needs to be declared in source so the linker can find it and actually give it an address to be referenced by. This may unnecessarily(depending on desired effects) cause inelegant code, especially if you're trying to create a header only library. You could solve it by converting the values to functions that return the value, which could open up the templates to run-time info as well.
"enum hack" is a more constrained and close-enough to #define and that helps to initialise the enum once and it's not legal to take the address of an enum anywhere in the program and it's typically not legal to take the address of a #define, either. If you don't want to let people get a pointer or reference to one of your integral constants, an enum is a good way to enforce that constraint. To see how to implies to TMP is that during recursion, each instance will have its own copy of the enum { val = 1 } during recursion and each of those val will have proper place in it's loop. As #Kornel Kisielewicz mentioned "enum hack" also supported by older compilers those forbid the in-class specification of initial values to those static const.