I could do struct initialization with code:
struct struct_type_id struct_name_id = { value1, value2, value3 };
but could not with:
struct struct_type_id struct_name_id;
struct_name_id = { value1, value2, value3 };
why I could do it with the former,but could not with the latter with gcc,g++,vc2008,vc6?In other words,why the c/c++ programming language do not support this syntax?
thanks.
The first statement creates a variable initialized to the given values, i.e., these values are built in memory and stored directly in the program executable in that variable address (for globals) or ready for memory copy (for stack variables).
The second statement of the second block is very different. Although it looks similar, it is an assign expression. It means that the RHS of the equals operator is an expression that is evaluated (independently of what is in the LHS of =), and then passed to the = operator. Without proper context, {...} doesn't have any meaning.
In C99, you can do this:
struct_name_id = (struct struct_type_id){ value1, value2, value3 };
Now the RHS of the equals operator is a valid expression, since there is proper context for the compiler to know what is in {...}.
In C++11, the syntax is:
struct_name_id = struct_type_id{ value1, value2, value3 };
I don't know why C didn't originally support some kind of syntax to 'reinitialize' a struct using something like the initializer list - there are definitely times when I would have found it handy. As Juliano mentioned, C99 (and C++0x) has fixed it to a certain degree, but I often have to stick with C90. When I want to do something like that, I'll sometimes do the following:
struct foo const init_foo = { 1, 2, 3};
struct foo myFoo;
// ....
myFoo = init_foo; // reinitialize myFoo
You just need to cast the values as such:
struct_name_id = (struct struct_type_id){ value1, value2, value3 };
I faced a similar problem, and the solution to that was that I was trying to initialized the struct outside the function(not using the initializer syntax, but with the obj.member = VALUE; notation). It is a related problem, so posting here, hoping someone with the same question lands up here.
Will this work for you ?
typedef struct name_id {int value1; int value2; int value3;} NAME_ID;
name_id mynameid = {0,1,2};
Related
I can't understand what's going there.
Using Visual Studio 2008, I've defined an enum like this:
enum MyType{
A,
B,
C
};
Then I use it to initialize a member variable:
class MyClass
{
private:
bool bit_;
uint16 num_;
MyType member_;
public:
MyClass(MyType value){
member_ = value; // This the assignment which fails
} // Here, there's a breakpoint to query member_ value
};
MyClass instance = new MyClass();
I'm using Debug configuration, so no optimization can fool me when reading
a variable. At a breakpoint just after the assignment, the debuger shows the value of member_ as member_ = C.
It could be a debugger whatch refresh issue but, inside a method it evaluates true when checking:
if(member_ == C){
// ??
}
And also, assigning to the other values gives strange numbers, e.g. doing member_ = B gives member_ = 258 when ferching it.
Can you tell me what's wrong? Thanks in advance.
EDIT #1
I've noted a funny effect which explains why after assigning member_ = A the expression member_ == C evaluates to true for the enum with the default values:
For the enum
enum MyType{ A, B, C}; // equivalent to enum MyType{ A = 0, B = 1, C = 2};
I get
MyType a = A; // but when fetching a the value is 2 (0x0002) thats the map for C!
MyType b = B; // but when fetching a the value is 258 (0x0102)
MyType c = C; // but when fetching a the value is 514 (0x0202)
But if I make
enum MyType{ A = 5, B = 6, C = 7};
I get
MyType a = A; // but when fetching a the value is 1282 (0x0502)
MyType b = B; // but when fetching a the value is 1538 (0x0602)
MyType c = C; // but when fetching a the value is 1794 (0x0702)
So, when assigning that #?!^% enum, the rule seems to be, shift 8 bits and add 2.
It sounds like compiler issues.
Btw, making the type of member_ to be int instead MyType doesn't changes nothing.
EDIT #2
Added two more members to the class, which are the real cause of the problem. I'll post the
answer as soon as the time restriction vanishes (8h from the posting of the question).
Enum entries does not have to have unique values. You might have an enum with A,B,C where both A and C are equal to '42'. In such case, when the var has value of 42, the IDE will show you only one of the matching entries, A or C, not both.
You can easily create an enum with 'duplicate' entries, like this:
enum { A=1, B=1, C=1 }
But most probably, you didn't do it like that. However, when using autonumbering, you can accidentally (or intentionally) create duplicates too:
enum { A, B, C } // 0,1,2
enum { A, B, C=0 } // 0,1,0
enum { A=2, B=1, C } // 2,1,2
enum { A=-1, B, C=0 } // -1,0,0
Be sure to double-check your enum definition.
see i.e. http://www.learncpp.com/cpp-tutorial/45-enumerated-types/
Thanks everyone.
Somebody at work pointed me to the origin of the problem.
It's a matter of faulty configuration of the project,
which gives data alignment issues.
After compiling, with the current project settings,
the two first members of the class are 3 bytes of size.
It should be 4 bytes, hence the misalignment of 1 byte.
The extra 2 added is garbage at the misaligned byte, so, the
whole effect is to shift one byte and add 2.
This effect is cancealed adding an extra member, although
it's not an elegant solution (the solution is to configure
the project corectly).
class MyClass
{
private:
bool bit_; // 1 byte
uint16 num_; // 2 byte
bool dummy; // extra byte to help the alignment
MyType member_;
public:
MyClass(MyType value){
member_ = value; // Now it works as expected.
}
};
I am looking for a solution using the C++03 standard (I am constrained to using this version of the standard for several years yet). Solutions for C++11 are also welcome, but will not be "accepted" as the answer to this question.
What is a simple, concise way that I can represent a set of related constant floating point values as a single type (similar to an enum) to ensure type-safety without incurring significant overhead and still allow me to operate on the values as floats directly?
The end result is that I would like to be able to do something like the following:
enum FloatingPointEnum
{
VALUE1 = 0.1234f,
...
VALUEN = 0.6789f
};
float SomeFunction(FloatingPointEnum value)
{
float new_value;
/* perform some operation using "value" to calculate "new_value" */
new_value = static_cast<float>(value); // <- a simplistic example
return new_value;
}
While I can think of several solutions, none of them are as clean/simple/straightforward as I would like and I figure that someone must already have an elegant solution to this problem (yet I cannot seem to find one in my searching).
EDIT:
I would like the following call to SomeFunction with a value that is not specified directly as a value from the enumerated type to fail to compile:
float nonEnumeratedValue = 5.0f
SomeFunction(nonEnumeratedValue);
someone must already have an elegant solution to this problem
There are lots of problems that have no elegant solution (and many that have no solution at all). What makes you think this problem has one? The closest you can get is to use a wrapper class.
class FloatingPointEnum {
float f;
FloatingPointEnum(float arg) : f(arg) {}
public:
static const FloatingPointEnum Value1;
static const FloatingPointEnum Value2;
operator float() const { return f; }
};
const FloatingPointEnum FloatingPointEnum::Value1(0.1234f);
const FloatingPointEnum FloatingPointEnum::Value2(0.6789f);
A possible alternative solution, not always applicable but very clean, is to use fixed precision.
Lets imagine you have you enum containing some distance in meters
enum DistancesMeter{
A = 0.25,
b = 0.05,
};
then you may simply switch to use mm
enum DistancesMM{
A = 250,
b = 50,
};
In C++11 you can use constexpr to achieve what you want.
constexpr - specifies that the value of a variable or function can appear in constant expressions
http://en.cppreference.com/w/cpp/language/constexpr
With constexpr you define a compile-time constant. This only works for literal types, such as float. Since at the same time we want
float nonEnumeratedValue = 5.0f;
SomeFunction(nonEnumeratedValue);
to fail, we cannot use a simple typedef. Instead we use Boost’s BOOST_STRONG_TYPEDEF.
#include <boost/serialization/strong_typedef.hpp>
BOOST_STRONG_TYPEDEF(float, FloatingPointEnum);
constexpr float VALUE1 = 0.1234f;
constexpr float VALUEN = 0.6789f;
float SomeFunction(FloatingPointEnum value)
{
float new_value;
/* perform some operation using "value" to calculate "new_value" */
new_value = static_cast<float>(value); // <- a simplistic example
return new_value;
}
Now you can call the function only with instances of FloatingPointEnum. Unfortunately, the instantiation syntax is not so nice anymore
FloatingPointEnum f {VALUEN};
Alternatively, you can simply use the D programming language, where floating point enums are supported and the following code works as expected:
enum FloatingPointEnum
{
VALUE1 = 0.1234f,
//...
VALUEN = 0.6789f
};
float SomeFunction(FloatingPointEnum value)
{
float new_value;
new_value = value; // No cast needed, welcome to D!
return new_value;
}
Calling SomeFunction with a float results in
Error: function test.SomeFunction (FloatingPointEnum value) is not callable using argument types (float)
Can I get the address of an object as a string constant in g++? Example:
struct s { } x;
If &x == 1234, then I need "1234" in my code.
EDIT:
By string constant I meant that I need that constant string at compile- or link-time. I need to embed it in inline assembly code like this:
template < typename U >
struct T {
static int x;
void f () {
asm (".word " some-expression-containing-(&x));
}
};
I don't know a way to construct the mangled name with a preprocessor macro, so I asked this question.
The solution doesn't need to be portable, g++ is sufficient.
The address itself is known at compile- or link-time though, as it would work to examine the assembly output and put in the mangled name into the inline assembly instruction.
I wonder why would you need that... but you can do this:
#include <sstream>
#include <cstddef> //for ptrdiff_t
....
stringstream ss;
ss << reinterpret_cast<ptrdiff_t>(&x);
ss.str() now contains your desired string
edit: If you want to do this compile-time... erm... I'll dare assume it's impossible?
template<class U>
struct T {
static int x;
void f () {
asm (".word %0" : "m" (&x));
}
};
This works for me in g++.
You can do
asm(".word x")
(it will work only for file-scope variables symbols as only they potentially get a symbol table entry). It's not constant expression, but the address is anyway not known until the program is fully linked.
In C, you could do this, but, in C, as you are using char *'s as your strings, you need something like this:
printf("%i-%i", &string[0], &string[strlen(string) - 1]);
That prints the range of memory the string is in, istead of the starting adress.
The error output operand constraint lacks = is because haven't operator = before of the operator out m. Take =m
I have a enumerated type StackID, and I am using the enumeration to refer to an index of a particular vector and it makes my code easier to read.
However, I now have the need to create a variable called nextAvail of type StackID. (it actually refers to a particular stackID ). I tried to increment it but in C++, the following is illegal:
nextAvail++;
Which sort of makes sense to me ... because there's no bounds checking.
I'm probably overlooking something obvious, but what's a good substitute?
I also want to link to this question.
I'm probably overlooking something obvious, but what's a good substitute?
Overloading operator++:
// Beware, brain-compiled code ahead!
StackID& operator++(StackID& stackID)
{
#if MY_ENUMS_ARE_CONTIGUOUS && I_DO_NOT_WORRY_ABOUT_OVERFLOW
return stackID = static_cast<StackID>( ++static_cast<int>(stackID) );
#else
switch(stackID) {
case value1 : return stackID = value2;
case value2 : return stackID = value3;
...
case valueN : return stackID = value1;
}
assert(false);
return stackID; // some compilers might warn otherwise
#endif
}
StackID operator++(StackID& stackID, int)
{
StackID tmp(stackID);
++stackID;
return tmp;
}
Because enumerations do not have to be contiguous. E.g. take this example:
enum Colors {
cRed, // = 0
cBlue, // = 1
cGreen = 3
}
What should happen in this scenario?
Colors color = cBlue;
Colors other = color++;
Should other be cGreen or should it be 2. In that case it's not a valid enumeration member anymore. What about this?
Colors color = cGreen;
Colors other = color++;
Should other be cRed (wrap around) or 4?
As you can see, being able to increment enumeration values introduces a whole lot of questions and complicates the simple mechanism that they intend to be.
If all you care about is the integer value being incremented, then simply cast to int and increment that.
Casting back and forth to/from int is of course the obvious solution, then you make clear that you understand that the addition is happening "outside" the enum:
nextAvail = static_cast<StackID>(static_cast<int>(nextAvail) + 1);
Why not store nextAvail as an int instead if you're going to do arithmetic operations on it?
Another option would be to wrap the enum in your own type and overload operator ++ for it (which also could wrap around or something for instance).
An enumeration is semantically supposed to represent a set of distinct related, values.
So you could have
enum Colour {RED, GREEN, BLUE};
But that should be equivalent to:
enum Colour {GREEN, BLUE, RED};
The problem is that if you increment an enum then those representations are not the same. GREEN++ in the first case is not the same as GREEN++ in the second.
Making your program dependent on the declaration of the enum is a recipe for disaster - maintainers may assume that the order of the enum doesnt matter, introducing many silent bugs.
Very Simple:
nextAvail = (StackID)(nextAvail + 1);
Enums are going to be type int, so you can cast them. Is this what you're trying to do?
int ndx = (int) StackID.SomeValue;
...
++ndx;
This is going to make someone very confused down the line, of course.
It occurs to me that you're using an enum where you should be using const, or even #define. enum is most appropriate when you have arbitrary values (where the exact value is not meaningful).
I've overloaded the ++/-- operator in this way:
enum STATE {STATE_1, STATE_2, STATE_3, STATE_4, STATE_5, STATE_6};
// Overload the STATE++ operator
inline STATE& operator++(STATE& state, int) {
const int i = static_cast<int>(state)+1;
state = static_cast<STATE>((i) % 6);
return state;
}
// Overload the STATE-- operator
inline STATE& operator--(STATE& type, int) {
const int i = static_cast<int>(type)-1;
if (i < 0) {
type = static_cast<STATE>(6);
} else {
type = static_cast<STATE>((i) % 6);
}
return type;
}
With respect to oprator++, $5.2.6/1 states- "The type of the operand shall be an arithmetic type or a pointer to a complete object type."
StackID does not fit the bill here. It is of enumeration type.
One option is like this
$5.7/1 - "For addition, either both operands shall have arithmetic or enumeration type, or one operand shall be a pointer to a completely defined object type and the other shall have integral or enumeration type."
enum Possibility {Yes, No, Maybe};
Possibility operator++(Possibility const& r){
return Possibility(r + 1); // convert r to integer, add 1, convert back to Enum
}
int main(){
Possibility p = Yes;
Possibility p1 = ++p;
}
I'm quite happy with this C plus C++ solution for a for loop incrementing an enum.
for (Dwg_Version_Type v = R_INVALID; v <= R_AFTER; v++)
=>
int vi;
for (Dwg_Version_Type v = R_INVALID;
v <= R_AFTER;
vi = (int)v, vi++, v = (Dwg_Version_Type)vi)
The other solutions here are not C backcompat, and quite large.
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);