Can all programs be broken down into if-statements? - if-statement

Probably a really stupid question, but whatever.
Theoretically speaking, everything is binary. Either a 1 or a 0.
Similar to an if-else.

Related

Do C++ compilers (optimizers) guarantee any code/executable invariants?

I am wondering if any C++ compilers (optimizers) guarantee that a code that is highly "decorated" with some meaningless operations (e.g. if (true) or do-while(false) pattern) will be generated (when compiling with all the optimizations for speed) into exactly the same executable that would be, if the source code didn't contain these "decorations".
I hope my question is clear - if not I will try to rephrase it is some way - anyway here is, why I am asking it, to make it more clear: I have a 'legacy' piece of c++ code that uses macros quite heavily. Some of them are expressions, so it might be good to wrap them into do-while(false), although these macros themselves contains instructions like "break" or "continue", so I came even further to "if(true)[MacroBody]else-do{}while(false)". So far, so good, maybe not very clean but all should be fine, however I noticed that my executable (MSVC, all optimizations for speed) grows by 2kB after such "decorating".
(My feeling is that the compiler, after making some initial optimizations, was glad enough by what it did so far and stopped making further optimizations. The bad thing is that I was unable to minimize the case - the difference in executable replicated only on real-life case. That's why I would like to ask, if any of you, more specialized in compiler construction, have some knowledge about it. If my perception was right, currently it might work a bit heuristically - like compiler coming to a conclusion: "Looks like I did quite many optimizations, it may be just enough")

Why uniform initialization (initialization with braces) is recommended?

I see a lot of different places that uniform initialization is recommended. Herb Sutter recommends it, and gives a list when not to use it. It seems that the general consensus is to use this syntax.
However, I don't see why. It has the problem of std::initializer_list takes precedence. Adding a std::initializer_list to a class can break code. With templates, it is not recommended to use. It seems to have more exceptions than the "old" way. None of these problems existed with the old way.
I fail to see why uniform initialization is superior. My conclusion is to keep using () syntax, and use {} only in the case of when I want to call a constructor with std::initializer_list.
Why? What does uniform initialization give?
forbids narrowing: good feature. But, as I have narrowing warnings turn on for all my code (because I want to know all narrowings in my code, not just at initializations), I don't need this feature too much.
most vexing parse: yeah, that's a problem, but I hit this very-very rarely. So it is not a reason (for me) to switch. This places, I may use {}.
is there anything else (maybe, I'm still learning new features of C++)?
With the "old" way, there were no rules to remember, no possible break-of-code. Just use it, and sometimes, very-very rarely, you hit the most vexing parse. That's all.
Is my thinking wrong somewhere?
It seems like you have a decent hold on the technical aspects and nwp raised the other concern I would mention, clarity, in the comments. So I think you have the information you need to make a decision.
That said, I think it's worth doubling-down and trying to highlight the importance of the clarity aspect. In my experience, code clarity is probably the single most importance thing to maintain in a code base. Particularly in terms of avoiding confusion and limiting time wasted on stupid bugs. I think we've all had the experience of spending far too long tweaking the flow of a piece of buggy code only to eventually discover that the issue was a typo or misunderstanding of the original intent.
And to be fair, it sounds like you've tried to address this by sticking to a style and tools that help address that. The standard argument, as nwp started, is that many people aren't okay with deviating from the naming conventions built into the language, nor with using IDEs. I personally sympathize with that logic but also understand why many disregard it as old-fashioned or even a non-issue (particularly for the case of IDEs).
When it comes to matters of clarity, though, I find it hard not to keep in mind that people are annoyingly good at ignoring minor details, even when they might help them. So the more context clues that can hint at where an issue might be the better. Syntax highlighting is great, but I wouldn't bet an evening of debugging on being able to notice something being yellow instead of orange. Yellow and using camel-case? Maybe. Yellow and using braces? Maybe.
Especially when you start getting into code written by someone else, or a long time ago, the more all these little hints start to matter.
At the end of the day, I think that's why people like it enough to recommend it. It's the kind of thing that might just stick out to you when it matters.
Also, a side note in response to your comment about narrowing. Enabling warnings for narrowing may allow you to ignore this benefit for now but in many cases people either 1) can't enable such warnings due to legacy code or 2) don't want to enable such warnings because they intentionally rely on such behavior in certain circumstances and would consider the warnings a nuisance. However, adopting list initialization in either case could help with not only preventing potential issues but also making clear the intent of a given line of code.
To get to the point, people all have different circumstances and preferences. Features like this increase of ways people can improve their code quality/readability while still working within whatever constraints they may have (self-imposed or otherwise).

Am I casting integer types too much?

I'm very new to Rust and I've been re-solving Project Euler questions. The thing is, I realised that I kept casting integer types (mainly i32-i64) around to fit my statement; for iterators, in loops, for function inputs, for conditionals etc. Is it normal?
I'm guessing I'm doing something wrong working with one-off functions going through PE and coming from mainly dynamically typed languages.
I always try to use the smallest possible (or most feasible) integral type for the problem and I feel like I should just go with i64 for everything and be done with it instead of so much casting around.
Which is a better/recommended approach, blanket i64 type or sensible integer types with casting in code?
edit: After the comments I wanted to clarify, this is not exactly a code-review query but about best practices and readability concerns as in which of the two choices are preferred. I reckon the performance impact of casting is negligible when not misused in loops.
Unrelated PS: I was doing P4 with a twist of prime factors, turns out there are no palindromes that are a product of two 4-digit primes and the largest one from two 3-digit primes is 99899
I always try to use the smallest possible (or most feasible) int type for the problem
Here you are. Optimization. (Because why else would you do that?)
Rust encourages you to think about the integer types. This leads to a better defined and explicit program behaviour, helps catch a certain type of bugs and lets you optimize.
But coming from a language that wasn't that meticulous you'd likely to overdo it. That's how our mind often works: when we encounter some new ability or skill we try to use it everywhere.
This is often a problem with Rust. The language would introduce programmers to certain new concepts (safe borrowing, zero-cost futures) and then as people we'd rush and jumble the things we had little experience with, borrowing ourselves into a corner or using the futures absolutely everywhere.
You're trying to optimize your program, using the smallest possible integer type, even though you feel it makes your life less comfortable. If you're asking this question on stackoverflow then I'd go out on a limb and say, yes, you're casting too much!
You probably know the Knuth's motto, that "premature optimization is the root of all evil".
Don't let over-optimizing ruin your programming experience. Optimize only when you're comfortable with it. When you want to!
If you're afraid of premature pessimization then save this fear for the algorithms. Remember that programming in most dynamic languages you don't have that much freedom to over-optimize and yet your dynamic language programs still work.

Is it really better to have an unnecessary function call instead of using else?

So I had a discussion with a colleague today. He strongly suggested me to change a code from
if(condition){
function->setValue(true)
}
else{
function->setValue(false)
}
to
function->setValue(false)
if(condition){
function->setValue(true)
}
in order to avoid the 'else'. I disagreed, because - while it might improve readability to some degree - in the case of the if-condition being true, we have 1 absolutely unnecessary function call.
What do you guys think?
Meh.
To do this to just to avoid the else is silly (at least there should be a deeper rationale). There's no extra branching cost to it typically, especially after the optimizer goes through it.
Code compactness can sometimes be a desirable aesthetic, especially if a lot of time is spent skimming and searching through code than reading it line-by-line. There can be legit reasons to favor terser code sometimes, but it's always cons and pros. But even code compactness should not be about cramming logic into fewer lines of code so much as just straightforward logic.
Correctness here might be easier to achieve with one or the other. The point was made in a comment that you might not know the side effects associated with calling setValue(false), though I would suggest that's kind of moot. Functions should have minimal side effects, they should all be documented at the interface/usage level if they aren't totally obvious, and if we don't know exactly what they are, we should be spending more time looking up their documentation prior to calling them (and their side effects should not be changing once firm dependencies are established to them).
Given that, it may sometimes be easier to achieve correctness and maintain it with a solution that starts out initializing states to some default value, and using a form of code that opts in to overwrite it in specific branches of code. From that standpoint, what your colleague suggested may be valid as a way to avoid tripping over that code in the future. Then again, for a simple if/else pair of branches, it's hardly a big deal.
Don't worry about the cost of the extra most-likely-constant-time function call either way in this kind of knee-deep micro-level implementation case, especially with no super tight performance-critical loop around this code (and even then, still prefer to worry about that at least a little bit in hindsight after profiling).
I think there are far better things to think about than this kind of coding style, like testing procedure. Reliable code tends to need less revisiting, and has the freedom to be written in a wider variety of ways without causing disputes. Testing is what establishes reliability. The biggest disputes about coding style tend to follow teams where there's more toe-stepping and more debugging of the same bodies of code over and over and over from disparate people due to lack of reliability, modularity, excessive coupling, etc. It's a symptom of a problem but not necessarily the root cause.

C++ style vs. performance?

C++ style vs. performance - is using C-style things, that are faster the some C++ equivalents, that bad practice ? For example:
Don't use atoi(), itoa(), atol(), etc. ! Use std::stringstream <- probably sometimes it's better, but always? What's so bad using the C functions? Yep, C-style, not C++, but whatever? This is C++, we're looking for performance all the time..
Never use raw pointers, use smart pointers instead - OK, they're really useful, everyone knows that, I know that, I use the all the time and I know how much better they're that raw pointers, but sometimes it's completely safe to use raw pointers.. Why not? "Not C++ style? <- is this enough?
Don't use bitwise operations - too C-style? WTH? Why not, when you're sure what you're doing? For example - don't do bitwise exchange of variables ( a ^= b; b ^= a; a ^= b; ) - use standard 3-step exchange. Don't use left-shift for multiplying by two. Etc, etc.. (OK, that's not C++ style vs. C-style, but still "not good practice" )
And finally, the most expensive - "Don't use enum-s to return codes, it's too C-style, use exceptions for different errors" ? Why? OK, when we're talking about error handling on deep levels - OK, but why always? What's so wrong with this, for example - when we're talking about a function, that returns different error codes and when the error handling will be implemented only in the function, that calls the first one? I mean - no need to pass the error codes on a upper level. Exceptions are rather slow and they're exceptions for exceptional situations, not for .. beauty.
etc., etc., etc.
Okay, I know that good coding style is very, very important <- the code should be easy to read and understand. I know that there's no need from micro optimizations, as the modern compilers are very smart and Compiler optimizations are very powerful. But I also know how expensive is the exceptions handling, how (some) smart_pointers are implemented, and that there's no need from smart_ptr all the time.. I know that, for example, atoi is not that "safe" as std::stringstream is, but still.. What about performance?
EDIT: I'm not talking about some really hard things, that are only C-style specific. I mean - don't wonder to use function pointers or virtual methods and these kind of stuff, that a C++ programmer may not know, if never used such things (while C programmers do this all the time). I'm talking about some more common and easy things, such as in the examples.
In general, the thing you're missing is that the C way often isn't faster. It just looks more like a hack, and people often think hacks are faster.
Never use raw pointers, use smart pointers instead - OK, they're really useful, everyone knows that, I know that, I use the all the time and I know how much better they're that raw pointers, but sometimes it's completely safe to use raw pointers.. Why not?
Let's turn the question on its head. Sometimes it's safe to use raw pointers. Is that alone a reason to use them? Is there anything about raw pointers that is actually superior to smart pointers? It depends. Some smart pointer types are slower than raw pointers. Others aren't. What is the performance rationale for using a raw pointer over a std::unique_ptr or a boost::scoped_ptr? Neither of them have any overhead, they just provide safer semantics.
This isn't to say that you should never use raw pointers. Just that you shouldn't do it just because you think you need performance, or just because "it seems safe". Do it when you need to represent something that smart pointers can't. As a rule of thumb, use pointers to point to things, and smart pointers to take ownership of things. But it's a rule of thumb, not a universal rule. Use whichever fits the task at hand. But don't blindly assume that raw pointers will be faster. And when you use smart pointers, be sure you are familiar with them all. Too many people just use shared_ptr for everything, and that is just awful, both in terms of performance and the very vague shared ownership semantics you end up applying to everything.
Don't use bitwise operations - too C-style? WTH? Why not, when you're sure what you're doing? For example - don't do bitwise exchange of variables ( a ^= b; b ^= a; a ^= b; ) - use standard 3-step exchange. Don't use left-shift for multiplying by two. Etc, etc.. (OK, that's not C++ style vs. C-style, but still "not good practice" )
That one is correct. And the reason is "it's faster". Bitwise exchange is problematic in many ways:
it is slower on a modern CPU
it is more subtle and easier to get wrong
it works with a very limited set of types
And when multiplying by two, multiply by two. The compiler knows about this trick, and will apply it if it is faster. And once again, shifting has many of the same problems. It may, in this case, be faster (which is why the compiler will do it for you), but it is still easier to get wrong, and it works with a limited set of types. In paticular, it might compile fine with types that you think it is safe to do this trick with... And then blow up in practice. In particular, bit shifting on negative values is a minefield. Let the compiler navigate it for you.
Incidentally, this has nothing to do with "C style". The exact same advice applies in C. In C, a regular swap is still faster than the bitwise hack, and bitshifting instead of a multiply will still be done by the compiler if it is valid and if it is faster.
But as a programmer, you should use bitwise operations for one thing only: to do bitwise manipulation of integers. You've already got a multiplication operator, so use that when you want to multiply. And you've also got a std::swap function. Use that if you want to swap two values. One of the most important tricks when optimizing is, perhaps surprisingly, to write readable, meaningful code. That allows your compiler to understand the code and optimize it. std::swap can be specialized to do the most efficient exchange for the particular type it's used on. And the compiler knows several ways to implement multiplication, and will pick the fastest one depending on circumstance... If you tell it to. If you tell it to bit shift instead, you're just misleading it. Tell it to multiply, and it will give you the fastest multiply it has.
And finally, the most expensive - "Don't use enum-s to return codes, it's too C-style, use exceptions for different errors" ?
Depends on who you ask. Most C++ programmers I know of find room for both. But keep in mind that one unfortunate thing about return codes is that they're easily ignored. If that is unacceptable, then perhaps you should prefer an exception in this case. Another point is that RAII works better together with exceptions, and a C++ programmer should definitely use RAII wherever possible. Unfortunately, because constructors can't return error codes, exceptions are often the only way to indicate errors.
but still.. What about performance?
What about it? Any decent C programmer would be happy to tell you not to optimize prematurely.
Your CPU can execute perhaps 8 billion instructions per second. If you make two calls to a std::stringstream in that second, is that going to make a measurable dent in the budget?
You can't predict performance. You can't make up a coding guideline that will result in fast code. Even if you never throw a single exception, and never ever use stringstream, your code still won't automatically be fast. If you try to optimize while you write the code, then you're going to spend 90% of the effort optimizing the 90% of the code that is hardly ever executed. In order to get a measurable improvement, you need to focus on the 10% of the code that make up 95% of the execution time. Trying to make everything fast just results in a lot of wasted time with little to show for it, and a much uglier code base.
I'd advise against atoi, and atol as a rule, but not just on style grounds. They make it essentially impossible to detect input errors. While a stringstream can do the same job, strtol (for one example) is what I'd usually advise as the direct replacement.
I'm not sure who's giving that advice. Use smart pointers when they're helpful, but when they're not, there's nothing wrong with using a raw pointer.
I really have no idea who thinks it's "not good practice" to use bitwise operators in C++. Unless there were some specific conditions attached to that advice, I'd say it was just plain wrong.
This one depends heavily on where you draw the line between an exceptional input, and (for example) an input that's expected, but not usable. Generally speaking, if you're accepting input direct from the user, you can't (and shouldn't) classify anything as truly exceptional. The main good point of exceptions (even in a situation like this) is ensuring that errors aren't just ignored. OTOH, I don't think that's always the sole criterion, so you can't say it's the right way to handle every situation.
All in all, it sounds to me like you've gotten some advice that's dogmatic to the point of ignoring reality. It's probably best ignored or at least viewed as one rather extreme position about how C++ could be written, not necessarily how it always (or ever, necessarily) should be written.
Adding to #Jerry Coffin's answer, which I think is extremely useful, I would like to present some subjective observations.
The thing is that programmers tend to get fancy. That is, most of us really like writing fancy code just for the sake of it. This is perfectly fine as long as you are doing the project on your own. Remember a good software is the one whose binary code works as expected and not the one whose source code is clean. However when it comes to larger projects which are developed and maintained by lots of people, it is economically better to write simpler code so that no one from the team loses time to understand what you meant. Even at the cost of runtime(naturally minor cost). That's why many people, including myself, would discourage using the xor trick instead of assignment(you may be surprised but there are extremely many programmers out there that haven't heard of the xor trick). The xor trick works only for integers anyway, and the traditional way of swapping integers is very fast anyway, so using the xor trick is just being fancy.
using itoa, atoi etc instead of streams is faster. Yes, it is. But how much faster? Not much. Unless most of your program does only conversions from text to string and vice versa you won't notice the difference. Why do people use itoa, atoi etc? Well, some of them do, because they are unaware of the c++ alternative. Another group does because it's just one LOC. For the former group - shame on you, for the latter - why not boost::lexical_cast?
exceptions... ah ... yeah, they can be slower than return codes but in most cases not really. Return codes can contain information, which is not an error. Exceptions should be used to report severe errors, ones which cannot be ignored. Some people forget about this and use exceptions for simulating some weird signal/slot mechanisms (believe me, I have seen it, yuck). My personal opinion is that there is nothing wrong using return codes, but severe errors should be reported with exceptions, unless the profiler has shown that refraining from them would considerably boost the performance
raw pointers - My own opinion is this: never use smart pointers when it's not about ownership. Always use smart pointers when it's about ownership. Naturally with some exceptions.
bit-shifting instead of multiplication by powers of two. This, I believe, is a classic example of premature optimization. x << 3; I bet at least 25% of your co-workers will need some time before they will understand/realize this means x * 8; Obfuscated (at least for 25%) code for which exact reasons? Again, if the profiler tells you this is the bottleneck (which I doubt will be the case for extremely rare cases), then green light, go ahead and do it (leaving a comment that in fact this means x * 8)
To sum it up. A good professional acknowledges the "good styles", understands why and when they are good, and rightfully makes exceptions because he knows what he's doing. Average/bad professionals are categorized into 2 types: first type doesn't acknowledge good style, doesn't even understand what and why it is. fire them. The other type treats the style as a dogma, which is not always good.
What's a best practice ? Wikipedia's words are better than mine would be :
A best practice is a technique,
method, process, activity, incentive,
or reward which conventional wisdom
regards as more effective at
delivering a particular outcome than
any other technique, method, process,
etc. when applied to a particular
condition or circumstance.
[...]
A given best practice is only
applicable to particular condition or
circumstance and may have to be
modified or adapted for similar
circumstances. In addition, a "best"
practice can evolve to become better
as improvements are discovered.
I believe there is no such thing as universal truth in programming : if you think that something is a better fit in your situation than a so called "best practice", then do what you believe is right, but know perfectly why you do (ie: prove it with numbers).
Functions with mutable char* arguments are bad in C++ because it's too difficult to manually handle their memory, since we have an alternatives. They aren't generic, we can't easily switch from char to wchar_t as basic_string allows. Also lexical_cast is more straight replacement for atoi, itoa.
If you don't really need smartness of a smart pointer - don't use it.
To swap use swap. Use bitwise operations only for bitwise operations - checking/setting/inverting flags, etc.
Exceptions are fast. They allow removing error checking condition branches, so if they really "never happen" - they increase performance.
Multiplication by bitshifting doesn't improve performance in C, the compiler will do that for you. Just be sure to multiply or divide by 2^n values for performance.
Bitfield swapping is also something that'll probably just confuse your compiler.
I'm not very experienced with string handling in C++, but from from what I know, it's hard to believe it's more flexible than scanf and printf.
Also, these "you should never" statements, I generally regard them as recommendations.
All of your questions are a-priori. What I mean is you are asking them in the abstract, not in the context of any specific program whose performance is your concern.
That's like trying to swim without being in water.
If you do tuning on a specific concrete program, you will find performance problems, and chances are they will have almost nothing whatever to do with these abstract questions. They will most likely all be things you could not have thought of a-priori.
For a specific example of this, look here.
If I could generalize from experience, a major source of performance problems is galloping generality.
That is, while data structure abstraction is generally considered a good thing, any good thing can be massively over-used, and then it becomes a crippling bad thing. This is not rare. In my experience it is typical.
I think you're answering big parts of your question on your own. I personally prefer easy-to-read code (even if you understand C style, maybe the next to read your code has more trouble with it) and safe code (which suggests stringstream, exceptions, smart pointers...)
If you really have something where it makes sense to consider bitwise operations - ok. But often I see C programmers use a char instead of a couple of bools. I do NOT like this.
Speed is important, but most of the time is usually required at a few hotspots in a program. So unless you measure that some technique is a problem (or you know pretty sure that it will become one) I would rather use what you call C++ style.
Why the expensiveness of exceptions is an argument? Exceptions are exceptions because they are rare. Their performance doesn't influence the overall performance. The steps you have to take to make your code exception-safe do not influence the performance either. But on the other hand exceptions are convenient and flexible.
This is not really an "answer", but if you work in a project where performance is important (e.g. embedded/games), people usually do the faster C way instead of the slower C++ way in the ways you described.
The exception may be bitwise operations, where not as much is gained as you might think. For example, "Don't use left-shift for multiplying by two." A half-way decent compiler will generate the same code for << 2 and * 2.