I can think I can vaguely remember seeing a few years ago a way to essentially enter a variable Structure and work on its members without calling the variable name every time. similar to how you can us "using namespace bla". It may have even been from pascal are some left field API that I have used.
e.g
typedef struct time{
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t period;
}time;
void clockFunct(){
static time clock{0,0,0,am};
/*SOME SYNTAX THAT I CANT FIND/REMEMBER*/ clock{
hour = 2;
minute = 30;
second = 20;
period = pm
};
}
I could create some local variables and pass it back but i'm working on micro-controllers so space is a bit of a premium... or just not be lazy and write out the structure name. Just thought I would put it out there and see if anyone knew what I was talking about
Since you did tag C++, you can kind of do what you want in the near future (though the advisability of it is questionable). c++17 sees the introduction of structured bindings to the language:
static time clock{0,0,0,am};
{
auto& [hour, minute, second, period] = clock;
hour = 2;
minute = 30;
second = 20;
period = pm;
};
Inside the block scope, those identifiers will refer (because of the reference qualifier) to the members of clock. And you don't need the block scope at all, actually. I just limited it to simulate the semantics you wanted more closely.
In C99, you can specify a designator in struct initialization
static time clock = { .hour =2, .minute =30, .second = 20, .period =pm };
There's no such syntax, you've probably seen it in other languages. Just write the correct member access operators, the code is normally more readable that way anyways.
That said, with your example code, you can assign the whole struct at once in C (not in C++) using a compound literal:
clock = (time){2, 30, 20, pm};
or, with designated initializers for more clarity (which also helps to avoid bugs):
clock = (time){ .hour=2, .second=30, .minute=20, .period=pm };
The language you're thinking of is C++, not C. And specifically, the behavior you're thinking of is seen in member functions.
We can change the function definition to void time::clockFunct() {. We'd first need to drop the typedef, though. That's actively problematic in C++ as it changes the meaning of time.
Note that it wasn't good C either - C has a function time() in the Standard Library.
Related
I am programming for a while now and I've started trying to improve my code. Since I really hate creating bazillion of variables that are used only once in long function, is it good practice to shorten variable scope by using brackets?
i.e.
instead writing:
void fcn()
{
int var1;
// some part of fcn
// use of var1;
// rest of fcn
}
write:
void fcn()
{
// some part of fcn
{
int var1;
// use of var100;
}
// rest of fcn
}
Yes it is indeed a good idea to keep the scope of variables as tight as possible.
In your case, unless you are absolutely certain that your code using var1 will only ever be used in fcn (and if my experience is anything to go by, I tend to misjudge that), you could split that code out to a separate function. Your program will scale better that way, and testing will also be simpler. Else, use scope blocks as you currently do.
There are certainly context in which this approach is a good practice.
It is so wide spreaded around 'if/range for/while/case' statements that explicit initializer in those statement were added in C++17 and C++20.
You shouldn't write int var1; anywhere.
Firstly var1 is a terrible name.
Secondly you now have the potential for undefined behaviour, if any code path can read var1 before it is assigned.
Prefer
int meaningfulName = initialValue;
Or even better
const int meaningfulName = value;
Having done that, the scopes you are choosing between are more restricted. If there is still a choice, prefer the narrowest scope possible.
I was coding with a beginner C++ group and we were creating a 'Car' class. Someone suggested 'tyre type' as a possible variable/attribute to the class as a boolean type. Another person then asked whether booleans should be directly answerable with a yes/no.
I was just wondering the same. How do you best manage a variable this and how do you later specify two options, such as winter/summer, for this variable?
Well, it depends.
Your goal is to write clear, readable, maintainable, and correct code. It's not so much that bool necessitates a yes vs. no answer as much as it is a question of whether or not using boolean (or any other type for that matter) helps you to meet these goals. If it makes your code clear, it's worth considering. If it makes things confusing, it's not a good idea.
For example, you may only have two types of tires, but consider a couple of things:
How do you know you won't add more later? You don't want to shoot yourself in the foot.
When writing / reading the code how do you remember that true is "summer" and false is "winter"? Will you have to maintain that info in your head / always look it up somewhere? Will it be easy to make a mistake? Will it confuse a reader who is unfamiliar with your code?
Think about those kinds of things. In your case, while using a boolean will certainly get the job done, I'd say it's a good use for an enum, even if you only have two values right now (or ever). E.g.:
enum TireType { WinterTire, SummerTire };
Now everything falls into place:
You can add new types in the future if you'd like, with no major issues.
A variable TireType t documents itself, we know just at a glance that t is a tire type.
There is much less of a chance of mistake when entering values: It'll be very hard to confuse WinterTire with SummerTire, whereas true and false discard all semantic meaning.
A boolean has two options, but those options are "true" or "false" (or, occasionally, "yes" and "no").
We do not generally represent other variables with two options as booleans.
If you have tyre types (of which there currently so happen to be two), I would suggest enums for this.
As always, there are exceptions. If your tyre types are "tyre with oil on it" and "tyre without oil on it", then you could use a boolean called tyreHasOilOnIt.
Really, it is up to you.
A boolean type is generally a value with precisely two values, one being truthy and the other falsy. This can to some degree be bent to other meanings. In your case when I saw discussion of tyre type I had no idea what the two values would mean untill reading the comments.
In my opinion when the value isn't self explanatory like this I would not use a boolean.
In your case, if the types of tyre are known at the time you write the program I would use an enum of some sort, and if they are not known just a plain string.
I would suggest don't use either enum or bool type for tyre type as a possible variable/attribute may change as you specified yes/no or Winter/Summer . Its better to use it as short int which values you can track or map with respect to yes,no,winter,summer . This will allow you to assign or change as per your need and class will never need a change.
Example :
Class car
{
// we will use tyre type to map enum
//type and other type if required
int tyreType;
};
enum tyre_type_t
{
//default value is considered 100
// since we can use previous
//value any other purpose.
WINTER = 100,
SUMMER
}
int main()
{
Car obj;
obj.tyreType = 1; // Yes
obj.tyreType = 0; // No
obj.tyreType = WINTER;
// Now we can assig enum.
// values //too.
return 0;
}
Happy Coding
Example :
Class car
{
// we will use tyre type to map enum
//type and other type if required
int tyreType;
};
enum tyre_type_t
{
//default value is considered 100
// since we can use previous
//value any other purpose.
WINTER = 100,
SUMMER
}
int main()
{
Car obj;
obj.tyreType = 1; // Yes
obj.tyreType = 0; // No
obj.tyreType = WINTER;
// Now we can assig enum.
// values //too.
return 0;
}
Happy Coding
While upgrading a legacy project to VS2015, I noticed there were a lot of errors where a local variable was redefined inside a function for example.
void fun()
{
int count = applesCount();
cout << "Apples cost= " << count * 1.25;
for (int bag=0; bag<5;bag++)
{
int count = orangesCount(bag);
cout << "Oranges cost = " << count * 0.75;
}
}
The error/warning message by compiler is:
declaration of 'count' hides previous local declaration
I know it is obviously not a good practice to use the same name for variable count but can the compiler really mess things up as well or generally they deal this situation rather gracefully?
Is it worth it to change and fix the variable names or is unlikely to cause any harm and is low or no risk?
I noticed there were a lot of errors where a local variable was redefined inside a function for example.
You are not demonstrating redefining here. You show an example of variable shadowing.
Variable shadowing is not an error syntactically. It is valid and well defined. However, if your intention was to use the variable from the outer scope, then you could consider it a logical error.
but can the compiler really mess things up
No.
The problem with shadowing is that it can be hard to keep track of for the programmer. It is trivial for the compiler. You can find plenty of questions on this very site, stemming from confusion caused by shadowed variables.
It is not too difficult to grok which expression uses which variable in this small function, but imagine the function being dozens of lines and several nested and sequential blocks. If the function is long enough that you cannot see all the different definitions in different scopes at a glance, you are likely to make a misinterpretation.
declaration of 'count' hides previous local declaration
This is a somewhat useful compiler warning. You haven't run out of names, so why not give a unique name for all local variables in the function? However, there is no need to treat this warning as an error. It is merely a suggestion to improve the readability of your program.
In this particular example, you don't need the count in the outer scope after the inner scope opens, so you might as well reuse one variable for both counts.
Is it worth it to change and fix the variable names
Depends on whether you value more short term workload versus long term. Changing the code to use unique, descriptive local variable names is "extra" work now, but every time someone has to understand the program later, unnecessary shadowing will increase the mental challenge.
IMHO, bad coding practice. Hard to maintain and read.
The compiler can discern between the outer variable and the internal variable.
With a good vocabulary (and a thesaurus), one doesn't need to use the same variable names.
Shadowing a variable (which is what this is) has completely well defined semantics, so the compiler won't mess it up. It will do exactly what it has been told, with well defined result.
The problem is (as is often the case) with the humans. It is very easy to make mistakes when reading and modifying the code. If one is not very careful it can be tricky to keep track of which variable with a given name is being referenced and it's easy to make mistakes where you think you are modifying one but in reality you are modifying another.
So, the compiler is fine, the programmer is the problem.
In my experience, compilers usually handle this issue pretty gracefully.
However, it is definitely bad practice, and unless you have a really compelling reason to do so, you should either reuse the old variable (if it logically makes sense to do so), or declare a [differently-named] new variable.
Can be very bad:
Consider this
std::vector<int> indices(100);
if (true) {
std::vector<int> indices(100);
std::iota(indices.begin(), indices.end(), 0);
}
// Now indices will be an all-0 vector instead of the an arithmetic progression!
In Visual Studio, compiling with Warning Level4 /W4 will output a warning even when disambiguating by prefixing with the implicit this pointer, like in this->Count:
warning C4458: declaration of 'Count' hides class member
Although the compiler rarely makes a mistake with the values, shadowing can be abused and get confusing overtime.
Below is an example of shadowing the Count member variable which should be avoided:
From the Unreal Coding Standard document.
class FSomeClass
{
public:
void Func(const int32 Count)
{
for (int32 Count = 0; Count != 10; ++Count)
{
// Use Count
}
}
private:
int32 Count;
}
One option to dealing with this would adding a prefix to the incoming argument name when shadowing occurs, like so:
class FSomeClass
{
public:
void Func(const int32 InCount)
{
Count = InCount;
for (int32 Counter = 0; Counter != 10; ++Counter)
{
// Use Count
}
}
private:
int32 Count;
}
When using RAII resources it may actually simplify the code to shadow variables and not create new variable names.
An example, a simple logger which writes to stdout when entering and leaving a block:
class LogScope {
private:
std::string functionName;
uint32_t lineNo;
public:
LogScope(std::string _functionName, uint32_t _lineNo) :
functionName(_functionName), lineNo(_lineNo) {
std::cout << "Entering scope in " << functionName << " starting line " << lineNo << std::endl;
};
~LogScope(void) {
std:: cout << "Exiting scope in " << functionName << " starting line " << lineNo << std::endl;
};
};
It could be used like:
void someFunction() { // First scope here.
LogScope logScope(__FUNCTION__, __LINE__);
// some code...
// A new block.
// There is really no need to define a new name for LogScope.
{
LogScope logScope(__FUNCTION__, __LINE__);
// some code...
}
}
Having said that, normally it is good practice, not to reuse your variable names.
Zar,
The compiler will handle this situation fine. In your example, the count variable is defined in two different scopes '{}'. Due to the scope of the variable, the assembly language will refer to two different addresses on the stack. The first 'count' might be the stack point, SP-8, while the inner count might be SP-4. Once transformed into an address the name is irrelevant.
I would not generally change working code for stylistic reasons. If the code is a mess then you run the risk of breaking it. Usually messy code doesn't have any good tests so it hard to know if you broke it.
If you need to enhance the code then certainly tidy up.
--Matt
I've come across some interesting findings relating to runtime detection that has spurred an interesting question. If I want to declare a global variable based off a condition, I can easily do so during pre-compilation with #ifdefs. However, this produces different binaries, and I am looking for a solution that can be realized during runtime so as to constrain behavior to a single binary.
Example
A classic example that I can perform with arrays or other data types (note, the data types here are all const and must remain so - mirroring the immutable behavior of an enum):
Original (Compile Time):
#ifdef CONDITION
static const int faveNums[] = {......};
#else
static const int faveNums[] = {******};
#endif
Modified (Run Time):
static const int conditonalFaveNums[] = {......};
static const int defaultFaveNums[] = {******};
static const int * const faveNums = IsConditionTrue() ? conditonalFaveNums : defaultFaveNums;
Common Pitfall (Scoping):
This is a common pitfall that will not work, as if/switch conditionals are scoped and therefore unable to be referenced later - thank goodness for the ternary operator!
if(IsConditionTrue())
{
static const int faveNums[] = {......};
}
else
{
static const int faveNums[] = {******};
}
Problem
However, the situation appears to change with enums. Let's try the run time solution, but with an enum this time:
enum conditionalFaveNums = {......};
enum defaultFaveNums = {******};
enum faveNums = IsConditionTrue() ? conditonalFaveNums : defaultFaveNums;
This will not compile.
Compile time defines (as with the first example) can solve this, but is there a way to solve this at run time by conditionally declaring a global enum in C++?
While you can't do exactly what you're asking - the difference between your array and enum examples being that the array is simply data, whereas the enum is a type, and type definitions must be resolvable at compile time - perhaps a more helpful answer is that this is a good thing.
Dynamic data should be represented in a dynamic data structure. std::set is a pretty close conceptual match to an enum, and provides many useful (and efficient) methods that may come in handy later. Even better might be defining an enum listing all possible values at compile time, and then dynamically constructing a set of these values based on runtime information. (The set is thus a proper subset of the enum's range.)
You cannot do this. Key points to remember:
Values of variables can be initialized differently based on run time information.
Types MUST be defined/set at compile time.
You can use
static const int * const faveNums = IsConditionTrue() ? conditonalFaveNums : defaultFaveNums;
since that says what faveNums is to be initialized to at run time, using run time information.
You cannot use
enum faveNums = IsConditionTrue() ? conditonalFaveNums : defaultFaveNums;
since that tries to define the type faveNums using run time information.
Is it possible to get access to an individual member of a struct or class without knowing the names of its member variables?
I would like to do an "offsetof(struct, tyname)" without having the struct name or member variable name hard coded amoungst other things.
thanks.
Sure. If you have a struct and you know the offset and the type of the member variable, you can access it using pointers.
struct my_struct {
int member1;
char member2;
short member3;
char member4;
}
...
struct my_struct obj;
short member3 = *((short*)((char*)&obj + 5));
That'll get the value of member3, which is 5 bytes on from the start of obj on an x86 computer. However, you want to be careful. First of all, if the struct changes, your data will be garbage. We're casting all over the place, so you get no type safety, and the compiler won't warn you if something's awry. You'll also need to make sure the compiler's not packing the struct to align variables to word boundaries, or the offset will change.
This isn't a pleasant thing to do, and I'd avoid it if I were you, but yes, it can be done.
C and C++ are compiled languages without built-in "reflection" features. This means that regardless of what you do and how you do it, one way or another the path will always start from an explicit hard-coded value, be that a member name or an compile-time offset value. That means that if you want to select a struct member based on some run-time key, you have no other choice but to manually create a mapping of some kind that would map the key value to something that identifies a concrete struct member.
In C++ in order to identify a struct member at run-time you can use such feature as pointers-to-members. In C your only choice is to use an offset value.
Another issue is, of course, specifying the type of the members, if your members can have different types. But you provided no details about that, so I can't say whether you need to deal with it or not.
We had a similar problem some years ago: A huge struct of configuration information that we wanted to reflect on. So we wrote a Perl script to find the struct, parse its members, and output a C++ file that looked like:
struct ConfField
{ const char* name;
int type;
size_t offset;
};
ConfField confFields[] = {
{ "version", eUInt32, 0 },
{ "seqID", eUInt32, 4 },
{ "timestamp", eUInt64, 8 },
// ... lots more ...
{ 0, 0, 0 }
};
And we'd feed the script with the output from gcc -E.
Nowadays, I understand that gccxml can output an XML file representing any C++ source that gcc can compile, since it actually uses the g++ front end to do the parsing. So I'd recommend pairing it with an XML-parsing script (I'd use Python with the lxml library) to find out everything you ever wanted to know about your C++ source.
Somewhere in your code you need to reference the data member in the struct. However you can create a variable that is a pointer to a struct data member and from then on you no longer need to reference it by name.
struct foo
{
int member1;
int member2;
};
typedef int (foo::*intMemberOfFoo);
intMemberOfFoo getMember()
{
if (rand() > RAND_MAX / 2) return &foo::member1;
else return &foo::member2;
}
foo f;
void do_somthing()
{
intMemberOfFoo m = getMember();
f.*m = 0;
}
The technical answer is 'yes' because C++ is Turing-complete and you can do almost anything if you try hard enough. The more practical answer is probably 'no' since there is no safe and easy way of doing exactly what you want.
I agree with GMan. What exactly are you trying to do that makes you think you need this technique?
Well you will have to set up some stuff first, but it can be done. Expanding on Samir's response
struct my_struct {
int member1;
char member2;
short member3;
char member4;
}
you can create a table of offsets:
my_struct tmp;
int my_struct_offsets[4]={
0,
(char*)&(tmp.member2)-(char*)&(tmp.member1),
(char*)&(tmp.member3)-(char*)&(tmp.member1),
(char*)&(tmp.member4)-(char*)&(tmp.member1)
}
this will take into account different alignments on different systems