Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I've been criticized (without real arguments) for using assign and compare like this in my c code:
if (!(buffer = malloc(1024))) {
// handle failure
}
instead of:
buffer = malloc(1024);
if (!buffer) {
// handle failure
}
To be clear: This is not about malloc() but only about doing assignments within condition statements.
Personally I prefer the prior version from an aesthetic point of view.
Also if I do a git grep -E "if \(\!\(.* = .*\)\)\) \{" in order to identify similar constructs in the current Linux kernel source I find a few hundred identical assignments inside if conditions, e.g. in net/ipv4/ipconfig.c:
if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) {
rtnl_unlock();
return -ENOMEM;
}
Also used frequently in boost:
// boost/lexical_cast/detail/converter_lexical.hpp
if (!(i_interpreter.operator <<(arg)))
return false;
// boost/iostreams/filter/newline.hpp:
if ((flags_ & f_has_LF) != 0) {
if ((success = boost::iostreams::put(dest, LF)))
flags_ &= ~f_has_LF;
} else if (boost::iostreams::put(dest, CR)) {
if (!(success = boost::iostreams::put(dest, LF)))
flags_ |= f_has_LF;
}
So - apart from your personal opinion - are there good technical arguments for or against doing an assignment and comparison in one statement?
As far as I can tell, the argument against your version tends to be along the lines of "people don't expect to see operations in a conditional". Indeed, when looking over C-like code it takes me a little extra mental effort to spot the socket, bind and listen calls when they're stuffed in an if, because I'm expecting an if's condition to check things, not do things.
But that's about it.
I honestly don't see a marked difference in readability. I prefer yours, actually.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am facing a problem of extracting arithmetic operation information from C++ source code. For example, I want to parse a C++ code such that I can find out the the line numbers for all the codes that conduct arithmetic operations as well as the name of the variables or literals involved in the operation and the corresponding operation type. I am interested in built-in types such as int and double as well as user-defined classes where arithmetic operators such as operator+, operator* are overloaded.
Any idea how this can be achieved?
Edit: I was hoping that some compilers might generate some intermediate results that I can utilize to achieve this goal. I did some search and it seems that libclang can generate some useful intermediate results, but I just want to get some suggestions before I spend too much time on digging into it.
You might be able use clang-query to do it. Getting the queries just right is a bit tricky, but the llvm ast matcher docs are quite useful providing examples for every matcher. It also prints line/col numbers for the matched results.
Example code:
struct complex { float r, i; };
int operator*(int a, complex b)
{
return 0;
}
int main()
{
int a = 0;
complex b;
return (a * a) + (a * b);
}
Example query that returns math expressions which have been overloaded:
match cxxOperatorCallExpr(anyOf(hasOverloadedOperatorName("-"),
hasOverloadedOperatorName("+"), hasOverloadedOperatorName("*"),
hasOverloadedOperatorName("/")))
Output:
return (a * a) + (a * b);
^~~~~
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Recently I have started looking into C++ from the basics and got to know (to my surprise) that I can give series of expressions in a single line separated by commas in some cases as below
//it'll execute all the expressions mentioned after condition seperated by comma
for(int i=0;condition;++i,++x,cout<<"in for loop"<<endl,z = z*2);
(x>y)? ++z,z1 = z*2, cout<<"printing statement"<<endl:cout<<"condition failed"<<endl,z = z/2;
Here, I have a confusion after this is working. Is it safe to code in that way or is there any problem coding in such a way?
Please clarify!!!
Correct me if i'm wrong anywhere, I'm just curious to know why most of the programmers don't use this way (I haven't seen such kind of lines anywhere)
The comma operator , evaluates each of its operands in sequence. In standardese, there is a sequence point between the evaluation of the left operand and the right operand.
In a expression which contains a comma operator, the value of the left operand is discarded and the expression takes on the value of the right operand. In both of the examples above, the comma operator is used in a void context, so none of the values are used.
So a statement like this where the value of the comma operator is not used:
exp1, exp2, exp3, exp4;
Is equivalent to the following sequence of statements:
exp1; exp2; exp3; exp4;
The first example is equivalent to the following:
for(int i=0;condition;) {
++i;
++x;
cout<<"in for loop"<<endl;
z = z*2;
}
And the second example:
if (x>y) {
++z;
z1 = z*2;
cout<<"printing statement"<<endl;
} else {
cout<<"condition failed"<<endl;
z = z/2;
}
Note that this is considerably more readable that the one-line versions. It's also easier to debug. Since debuggers typically step through code a line at a time, it breaks up the flow and is more granular.
Not indenting and spacing your code is not less costly regarding performance. It is unreadable, confusing and a pain to understand for you and for anyone who'd have to work with it.
Lot of people will prefer a well-syntaxed, beautifully and efficiently-indented code than a top-performance one. You can modify, debug and refract a code which might not work but has the advantage to be understandable.
On the other hand, very few codes remain unchanged and stay unread. There will always be a time when someone, may be you, will have to read it again and if it looks like the one if your OP, it will be very time costly to do.
It is allowed. In my opinion and i say without a reference that in general other programmers do not find your 'for' loop very readable. Sometimes in a for loop you want to do other things then just for (int i = 0; i < 10; ++i){"do something"}For example increment 'i' in every loop with two. Reading code should be like reading a text. If you are reading a book you do not want it to be unnecessary difficult.
Your other question was about the safety of the statement. The biggest problem with the code is that you might get confused about what you are doing exactly. Bugs are caused by human errors (computers are deterministic and are executing machine code which ultimately has been written by a human) and the question about safety mainly depends on how you define it.
To give you some tips. When i just started programming C++ i looked a lot on CPP reference. I will give you a link where you can read about the syntax and what is allowed/possible. On this website there are quite a lot of examples on all kinds of statements. They will in general not put 5 or 6 operations within in a single line. If there are more variables that you want to change then you might want to do that in the scope of the for loop so it will be more readable instead of inside the for loop.
http://en.cppreference.com/w/cpp/language/for
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Why does List MakeEmpty(List L) have to be written in a form like:
List
MakeEmpty(List L)
in Mark Allens Book?
This is just a matter of styling preference; the command here is the same regardless of whether you write:
List
MakeEmpty(List L)
or
List MakeEmpty(List L)
It really doesn't make a difference besides changing the readability of the code. The author of the book you mentioned may find adding some whitespace more readable compared to the conventional method you compared it to.
One way you can differentiate between whitespace and a real compiling difference is the semicolon. Wherever there is a semicolon, the line terminates. In your case, if there was:
List; // Notice semicolon here
MakeEmpty(List L)
Then this would have changed the code (the syntax is wrong here as it changes the original meaning of the code, but I just wanted to make my point with this example).
Adding whitespace makes the code more readable to the programmer; it adds to the style, especially if it is being presented to a larger audience. The amount of whitespace preferred varies from person to person.
I tried to make the simplest example possible here: the main() function. See the 2 ways I wrote it:
Method 1:
int // Return type of function on different line from function name and arguments for function declaration
main(void)
{
cout << "hello" << endl;
return 0;
}
Method 2:
int main(void) // Return type of function on same line as function name and arguments for function declaration
{
cout << "hello" << endl;
return 0;
}
Just like your function declaration, here, the return value data type's position is changed between the 2 samples of code. However, the output is the same: It outputs hello followed by an endline.
Hope this helps. If I've made a mistake anywhere, or you have further questions, ask me in the comments box.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
For example, I have a method which accepts some arguments like
method1(int i)
the argument int should be either 1 or 2
I can use assert (i == 1 || i ==2)
or throw exception if (!(i==1) || (i==2)) throw std::exception
which one is better. I am always confused about assert vs explicit throw.
It really depends on the situation.
There are four major groups of error handling:
assert - used to deal with programming errors ("We don't expect this function to get a NULL pointer, and if it does, it's because some other part of our code is broken, and it should NEVER happen"). If the assert wasn't there, the code would probably crash, loop forever, or otherwise "fail".
exceptions - such as std::invalid_argument - this is more used when the program EXPECTS things to go wrong, and there is some way to "try again". More likely when the actual user is using the program wrong - e.g. inputs from keyboard/file, etc. As the name states, this should be an "exception" - something unusual and unexpected.
return value - when an error is entirely likely (trying to see if the serial port is on port COM1, COM2, COM3 or COM4 or "is the result of the equation matching what I expect yet?")
Let it crash - if the inputs are wrong, the application runs out of memory, etc, just crash. It may seem like a rough method, but sometimes there's not much better you can do anyway - what are you going to ACTUALLY do in the middle of your compiler if some linked list is broken and the next node is not pointing at your special sentry pointer, but to NULL? Printing a message may be a little better, but not a huge amount.
Is the integer passed to method1 always going to be done so by a programmer, or might it be passed in by the users of your application?
Assert,
for example if your code looks like this:
int i;
if ( condition ) {
i = 1;
}
else {
i = 3;
}
method1(i);
If this is the case, you'd likely want to use an assert, because it indicates you (the programmer) has made an error. If i = 3, you want your program to blow up and make it obvious there is a problem in your code, so you can catch it before you release it to your clients.
Throw an exception,
on the other hand, if your code looks like this:
int i;
cin >> i;
method1(i);
You're passing the user's input to the function. You can't anticipate what they might enter. So if it's an invalid value, you should throw an exception or return an error code and handle it accordingly (e.g., print out a message to the user saying they have entered an invalid number).
Generally asserts are checked in debug builds but not release builds. If you want to save time and skip the check in your final released code, then asserts are the way to go. If your function needs to blow up in the face of unexpected input even in release, then the exception may be the way to go.
Of course the details of exactly what you should do for error conditions will vary with context beyond what was provided in your example.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
So, before quite some exposition, here comes my question:
Why is there no support for multiple return variables/values in C++ (yet)?
To give you some more notes:
What (if any) is conceptually a problem with multiple return values and c++?
Is there something in the way the compiler implements returing a values from a function which makes multiple return values impossible/inefficient?
Having worked a lot with lua recently I've come to ask myself why C++ does not permit to return multiple values/variables from a function. To illustrate, let me give you a lua example:
-- get the first four values of the fibonacci sequence
local function fib4()
return 1, 1, 2, 3
local fib0, fib1, fib2, fib3 = fib4()
Being able to return multiple variables/values at once is a very useful feature indeed, which I typically emulate in the C++ world by creating structs (essentially collecting the variables in a wrapper) which are returned by the function in question. If one uses this approach a lot, the soure files will be cluttered with structs each containing some variables; none of these struct needs to be an actual object (and is implemented as a complete object). In a way the conceptual problem is somewhat similar the one resulting from using structs for creating functors [instead of lambdas]:
It destroys locality
It introduces objects which are not conceptually objects but rather a helper
On the pro side it increases code readability:
struct point_three_dim_t {
double x;
double y;
double z;
};
point_three_dim_t point = getCollisionPoint();
However, a priori you don't know whether the members representing the coordinates are named x, y and z or first, second and third. So again, you have to check how point_three_dim_t was defined. This would not be the case if
double x, y, z = getCollisionPoint();
were correct syntax.
Using C++11 we can achieve conceptually the same by using either std::tuple or std::tie
std::tuple<double,double,double> getCollisionPoint();
// Using std::tie
double x, y, z;
std::tie( x, y, z ) = getCollisionPoint();
// Using std::tuple
std::tuple<double,double,double> point = getCollisionPoint();
This gets us much closer to clean and local code, however, I think neither syntax is quite as appealing as the one I'm used from scripting languages like lua.