Ok guys I asked a question 15 mins ago and closed it because when I tried a simple test in main(), it worked. However, it does not work in the actual code:
Background, I have an array of unsigned ints which I cannot access via an unsigned short indexer. If I declare an array on the stack it works, but it doesnt work for my array data member.
Here is the array declaration:
typedef unsigned int uint;
class OB{
public:
OB();
void x(unsigned short side_pos);
private:
uint best_p[2];
};
and here's the code where I get the compiler error:
void OB::x(unsigned short side_pos){
unsigned int best_price = best_p[side_pos];
}
If I do:
void OB::x(unsigned short side_pos){
unsigned short something_else = 1;
unsigned int best_price = best_p[something_else];
}
I also get the compiler error, which is:
OB.cpp: In member function ‘void OB::x(short unsigned int)’:
OB.cpp:62:56: error: invalid types ‘unsigned int[short unsigned int]’ for array subscript
unsigned int best_price = best_p[side_pos];
It compiles on my computer. Seems the way to get that error is to use a variable instead of an array. Check the names of your attributes.
Based on intuition and comment hints, you have a local variable best_p (an unsigned int by the looks of it) that's shadowing the member of your class. Thus, best_p[side_pos] will use the local variable, not the data member.
If you want the compiler to catch shadowing, the -Wshadow option should do it. The best thing to do when it does is rename something. Having a convention for data member names (m_<name> is a common one) can also help to prevent both accidental shadowing and thinking about what to rename something to.
Related
I've used std::bind before and I think am close on this usage but not quite there and I don't have a clue how to resolve the compile error.
The ultimate goal is a medium-sized array of pointers to a small number of functions, with different parameters in each array element. At this point I just have one function and one table entry. If I can get that right I think I can solve the rest. I want to use std::function so that I can put the varied parameters into the array.
Here's declaration of the one function so far:
static Get *MakeGArrayStatic(void *Subscript, const void **array, unsigned int sizeOfArray);
Here's the declaration of the single pointer that will be typical of the array:
typedef std::tr1::function<Get *(void *, const void**, unsigned int)> GetMaker;
static GetMaker *gm1;
Here's the definition of the pointer:
Get::GetMaker *Get::gm1 = std::tr1::bind(&MakeGArrayStatic, &OutMsg::CurrentSeverity, FacSevTbls::SyslogSeveritiesForMessages, FacSevTbls::NumberOfTrueSeverities);
(Get is a class, CurrentSeverity is an enum, SyslogSeveritiesForMessages is a const char **, and NumberOfTrueSeverities is a size_t.)
The error I am getting (VS 2010) is
error C2440: 'initializing' : cannot convert from 'std::tr1::_Bind<_Result_type,_Ret,_BindN>' to 'Get::GetMaker *'
with
[
_Result_type=Get *,
_Ret=Get *,
_BindN=std::tr1::_Bind3,SyslogEnums::SeverityEnum *,const char **,size_t>
]
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
Can anyone please point out where I am going wrong?
Thank you again to #PlinyTheElder but I think we have left the question "officially" unanswered. Closing the loop, here are the declarations with the first cut at an array of functions:
static Get *MakeGArrayStatic(void *Subscript, const char **array, size_t sizeOfArray);
static Get *MakeGStatic(void *field, size_t sizeOfField);
typedef std::tr1::function<Get *()> GetMaker;
static GetMaker gm[];
and here is the definition of the array so far:
std::tr1::function<Get *()> Get::gm[] = {
std::tr1::bind(&Get::MakeGArrayStatic, &OutMsg::CurrentSeverity, FacSevTbls::SyslogSeveritiesForMessages, FacSevTbls::NumberOfTrueSeverities),
std::tr1::bind(&MakeGStatic, Msg::MessageID, 8) } ;
And here is a trivial example of a call to a function:
Get *g = Get::gm[0]();
Came out better than I had hoped. I had pictured that all of the "little functions" were going to have to have the same signature (like overloads). Compiles cleanly on both target compilers. (Have not tested execution yet, but I am confident.) Thanks again!
Update: yes, it executes.
I'm playing a bit with the C++ syntax to figure out a generalized way to keep track of an offset within a class, sort of like offsetof, but in a type-safe way and without #defines
I know that a template class can be template-parametrized with fields, besides types and constants. So I came out with this prototype:
#include <iostream>
template <typename class_type, typename field_type>
struct offsetter
{
offsetter(const char* name, field_type class_type::*field)
: name(name)
{
fprintf(stderr, "%zu\n", field);
}
const char* const name;
};
struct some_struct
{
float avg;
int min;
int max;
struct internal
{
unsigned flag;
int x;
} test;
char* name;
};
int main()
{
offsetter<some_struct, float>("%h", &some_struct::avg);
offsetter<some_struct, int>("%h", &some_struct::min);
offsetter<some_struct, char*>("%h", &some_struct::name);
offsetter<some_struct, some_struct::internal>("x", &some_struct::test);
return 0;
}
This code is actually able to print the field offset, but I'm not really sure on what I'm doing here. Indeed it feels utterly wrong to reference field without referring to an instance (foo.*field).
But it does the job: it prints the offset. My guess is that I'm hitting on some loophole though, since for instance I can't assign size_t offset = field.
I figured out I probably want something like this:
size_t offset = (&(std::declval<class_type>().*field) - &(std::declval<class_type>()))
Which however wont' work as I can't take the address of an xvalue:
taking address of xvalue (rvalue reference)
Is there any way to do this?
AFAIK there isn't a standard way of doing this. Even the standard offsetof is defined only for standard layout types.
What you are doing is UB. You are using the wrong specifier zu. There isn't much you can do with a member pointer. You can't even do pointer arithmetics on them, you can't convert to char* nor to an integer type.
Also if your assumption is that a member pointer is just an integer representing the offset from the beginning of the structure that is false, not only in theory, but also in practice. Having multiple inheritance and virtual inheritance made sure of that.
Hi I am writing little modified code for the bootloader for MCU's. The modification I am trying to do is power the boot loader even for an watchdog timer reset.
I am using this function prototype to define the address of the boot loader and I get the error :
invalid conversion from 'long int' to 'void (*)()' [-fpermissive]
My code is
#if defined ( __AVR_ATmega1284P__ )
void (*boot_start)(void) = 0xF000;
#elif defined ( __AVR_ATmega2560__ )
void (*boot_start)(void) = 0x1F000;
#endif
Where the 0xF000 and 0x1F000 are memory spaces. I don't get this error if my code is `
void (*boot_start)(void) = 0x0000;
Why ??
Compiler recognize 0xF000 as int and discard assigning this value to pointer. You should cast it explicitly:
void (*boot_start)(void) = (void (*)())0xF000;
0x0000 is just another name for NULL and will compile ok as a pointer value, but the other values need to be explicitly cast to the correct type.
The answer that I got from AVRFreak forum,
USE TYPEDEF,
typedef void (*fptr_t)(void);
fptr_t boot_start = (fptr_t)0xF000;
...
boot_start();
The reason you get the warning otherwise is that 0xF000 is a long int for an AVR. The thing on the left of '=' was a pointer to a function. So you are trying to assign an integer to a pointer. C thinks this is probably a mistake (often it is!) so it warns you. The way you quell that warning is to say "no this 0xF000 number really is a pointer value". The way you do that is with a typecast. Now you could do this with (wait for it):
void (*boot_start)(void) = (void(*)(void))0xF000;
But as you can see in that there is almost exactly the same (quite complex) structure on both side of the equals. So it makes sense to put all that detail into one single typedef and use it in multiple places.
If the function type were more complex this might even be something like:
int (*boot_start)(char, long, int *) = (int (*)(char, long, int *))0xF000;
and this starts to look very silly indeed - not only is it very likely you make a typing error it's just trying to remember the syntax here is a real pain! So you use typedef to define the function interface just once:
typedef int (*myfn_t)(char, long, int *);
myfn_t boot_start = (myfn_t))0xF000;
and that gets to be easier to type and easier to manage. If you later add a fourth char ** parameter to the function you now do it in just one place - the typedef.
Thanks to C Lawson and Yuriy.
I am new to structure programming, and I find it quite confusing when trying to pass a structure of array in c++. I have a project to do for college, a Star Trek game. This is the sample code:
void main_menu(char,char [][sz2],int&,struct enterpriseSt*,struct klingonSt*[100]);
void combat_menu(char [][sz2],struct enterpriseSt*,int&,struct klingonSt*[100]);
struct enterpriseSt
{
int energy_level;
int damage;
int torpedo_count;
};
struct klingonSt
{
int energy_level;
int damage;
int position[2];
};
int main()
{
struct enterpriseSt enterprise;
enterprise.energy_level=energy_ent_max;
enterprise.damage=0;
enterprise.torpedo_count=10;
struct klingonSt klingon[100];
main_menu(command,galaxy,turn,&enterprise,&klingon);
return 0;
}
void main_menu(char command, char galaxy[][sz2],int& turn,struct enterpriseSt * enterprise,struct klingonSt * klingon[100])
{
combat_menu(galaxy,enterprise,turn,klingon);
}
I have two structures, enterpriseSt and klingonSt. I can pass enterprise no problem, but with klingon I am struggling. I get all kinds of errors, doesn't matter what combination I use. The current one is:
error: cannot convert ‘klingonSt (*)[100]’ to ‘klingonSt**’ for argument ‘5’ to ‘void main_menu(char, char (*)[64], int&, enterpriseSt*, klingonSt**)’
I've made such a mess with it now. Could someone please explain it to me why it works with enterprise but not with klingon?
I use g++ compiler on Ubuntu. Thanks.
Your problem is in misunderstanding the arguments parsing rules.
you think that struct klingonSt*[100] is a pointer to the array of size 100 of type struct klingonSt, but actually when argument parsing, array and function symbols that should be situated on the right of token has higher priority, than symbols on the left of expression.
So, lets first write the expression with argument name included:
struct klingonSt*var[100]
and parse it
var
is an array of size 100 (as array symbol on the right has higher priority, than pointer on the left)
of pointers
to the type struct klingonSt
so, struct klingonSt*var[100] is actually is array of size 100 of pointers to struct klingonSt.
to pass a pointer to the array of size 100 of type struct klingonSt you should change parsing precedence using parenthesis:
struct klingonSt(*var)[100]
or
struct klingonSt(*)[100]
If you change your definition, your code will compile fine.
I think you're a bit confused on passing arrays to functions. When this is done, the array decays into a pointer to the first element of the array. You can declare the parameter as an array, but the array range is ignored by the compiler, and not enforced at runtime. Thus, for this style of coding, you'd just want to pass the array as a pointer, and length as a separate parameter (I've omitted your other params for clarity):
void main_menu(enterpriseSt*, int enterpriseCount, klingonSt*, int klingonCount);
Some alternatives to consider:
Adopting a modern C++ style, and use std containers like vector/list, passing them by reference.
void main_menu(vector<enterpriseSt> & enterprises, vector<klingonSt> & klingons);
Or, using a template wrapper to pass sized local arrays implicitly:
template<size_t eCount, size_t kCount>
void main_menu(enterpriseSt (&enterprises)[eCount], klingonSt (&klingons)[kCount])
{
main_menu(enterprises, eCount, klingons, kCount);
}
The problem that
struct klingonSt * klingon[100]
is an array of 100 struct klingonSt * rather than a point to 100 struct klingonSt
use struct klingonSt klingon[][100] instead.
If I am using an int as the array size when declaring a new array lint complains. What is the correct way to resolve this:
I could statically cast int to unsigned but that looks a bit odd...
What is the best way to resolve this without changing the use of an array and the need for integer as size?
MapItemPtr* pMapItems = new MapItemPtr[ (unsigned int)iRecordCount ];
Could do:
MapItemPtr* pMapItems = new MapItemPtr[static_cast<unsigned int>( iRecordCount )];
Is this the correct way to resolve the lint error:
Line 3811 Error 737: Loss of sign in promotion from int to unsigned int
or is there a more elegant way?
Since iRecordCount is clearly intended to hold a nonnegative integer, why not just declare it as unsigned int in the first place?
The error is not the constness of the variable, as the lint said:
: Line 3811 Error 737: Loss of sign in promotion from int to unsigned int.
You have a few options:
1 - static_cast<> int to unsigned int,
2 - (unsigned int*) c-style cast, but that should be avoided in c++ code.
3 - create a temporary unsigned int variable that will create the vector for you.
since you are just creating an array, the type of the variable could be size_t, declared in cstddef.