I++ vs i+=1
-
I think shorthand operators aren't the problem. Unclear code is the problem. Particularly, in this case, multiple assignments in one statement are something you need to be wary of.
I think I could defend the position they need to be related, such as in my
*s++ = 'x'
example above.
-
C and C++ would get a by for me. i don't do systems programming or embedded so none of my projects have a lick of C in them. it's all higher level languages.
-
I think I could defend the position they need to be related, such as in my
*s++ = 'x'
example above.
Maybe in 1976, but with today's optimising compilers, I'd prefer readable code.
-
++ isn't atomic. = isn't atomic. Why should += be atomic?
-
One int type for all loop counters will suffice.
If you're going to do that you might as well just use int. The only reason OTTOMH I can think of for declaring loop counter types is for range-checking.
-
Actually, that's a good point. In C# at least, nothing is guaranteed atomic; that's why
Interlocked.Increment()
et al exist.Forgot about that earlier
-
-
Maybe in 1976, but with today's optimising compilers, I'd prefer readable code.
Readable is subjective. In my opinion,
list[i++] = "hello"; list[i++] = "world";
is more readable than
list[i] = "hello"; i++; list[i] = "world"; i++;
and less error-prone than
list[i ] = "hello"; list[i+1] = "world"; i += 2;
though in an object-oriented language I'd agree it would be better to use
list.append("hello"); list.append("world");
-
Readable is subjective. In my opinion,
list[i++] = "hello"; list[i++] = "world";
is more readable than
list[i] = "hello"; i++; list[i] = "world"; i++; ```</blockquote> But in the former, you're embedding arithmetic inside an indexer, and for me that's a huge pile of <img src="/uploads/default/16378/36afe00aba128798.png" width="290" height="300"> Seriously, it just reeks; much better to have the increments outside of the indexers. As for this @PleegWat <a href="/t/via-quote/9028/158">said</a>:<blockquote>``` list[i ] = "hello"; list[i+1] = "world"; i += 2; ```</blockquote> yes it can be more error-prone if you're careless, but to me it's the most sensible way of doing it. Although, if you have more than a half-dozen lines, you're probably better off rethinking your data model ;)
-
Although, if you have more than a half-dozen lines, you're probably better off rethinking your data model
Agreed. And of course examples are artificial, and some of the offenders in our codebase I'd love to rewrite.
For example, a bytecode generator/interpreter for a homegrown string matching language, which most of the business logic is written in. I've recently taking the stance I'm not doing big work on that without replacing that completely. If I could I'd drop in regex instead, and I'd get support from all parties involved if there wasn't that one feature regex doesn't have...
-
But in the former, you're embedding arithmetic inside an indexer, and for me that's a huge pile of
<snip what="huge image" />
Seriously, it just reeks; much better to have the increments outside of the indexers.IMO common enough for me to expect mostly everybody to be familiar (and comfortable) with it. Guess not. :-/
Besides, you can swap the lines easily (and error-free) with the inline increment (because e.g., once again, someone decided to use BGR instead of RGB or whatnot).
-
list[i] = "hello"; i++; list[i] = "world"; i++;
Problem solved ;)
-
list[i] = "hello"; i++; list[i] = "world"; i++;
Problem solved ;)Fair enough - at that point it's mostly down to personal preference.
-
:do_not_want.png:
-
Actually, that's a good point. In C# at least, nothing is guaranteed atomic; that's why Interlocked.Increment() et al exist.
http://www.ecma-international.org/publications/standards/Ecma-335.htm
I.12.6.6
A conforming CLI shall guarantee that read and write access to properly aligned memory locations no larger than the native word size (the size of type native int) is atomic (see §I.12.6.2) when all the write accesses to a location are the same size. Atomic writes shall alter no bits other than those written. Unless explicit layout control (see Partition II (Controlling Instance Layout)) is used to alter the default behavior, data elements no larger than the natural word size (the size of a native int) shall be properly aligned. Object references shall be treated as though they are stored in the native word size.
[Note: There is no guarantee about atomic update (read-modify-write) of memory, except for methods provided for that purpose as part of the class library (see Partition IV). An atomic write of a “small data item” (an item no larger than the native word size) is required to do an atomic read/modify/write on hardware that does not support direct writes to small data items. end note]
[Note: There is no guaranteed atomic access to 8-byte data when the size of a native int is 32 bits even though some implementations might perform atomic operations when the data is aligned on an 8-byte boundary. end note]
-
…isn't that basically what I said? After all,
Interlocked
does its magic with atomic locks.Useful info though ;)
-
…isn't that basically what I said?
It also means that operations that fit within the machine's word size are atomic, as long as it's operating on another value that fits within the machine's word size. So basically operations on bool, byte, int16, int32, int64 (on 64-bit machines) can be atomic.
i++
is atomic in C#.Note that that includes object references. So
oldList = newList
is also atomic.
-
i++
is atomic in C#.
In the right circumstances, yes, but it's not a cast-iron guarantee.
-
In the right circumstances, yes, but it's not a cast-iron guarantee.
It's right there in the spec.
-
Is it worth reading the 100 posts above, or are they just a generic language lawyership argument?
-
So
i++
is atomic ifi
is anInt64
on a 32-bit machine? Because, by that very spec, it's not
-
So i++ is atomic if i is an Int64 on a 32-bit machine? Because, by that very spec, it's not
-
Is it worth reading the 100 posts above, or are they just a generic language lawyership argument?
You'll never know unless you try. ;)
-
-
What a twist!
-
I think I'm actually wrong on this. The spec guarantees reads and writes are atomic, but it doesn't guarantee that
i++
(which is a read, followed by an addition, followed by a write) is atomic.Huh.
In which case, it's really saying nothing at all, because how can the read or write of a single word-sized value not be atomic? The CPU kind of requires it to be.
-
I've been guilty of the following pattern in my code before:
[code]
private static uint lastAssignedID = 0;// [...]
public int AllocateID()
{
return lastAssignedID++;
}
[/code]But that's the most "clever" I've ever been with ++ or --, most of the time I just use it as a single statement like "i++;" or whatever.
-
[https://c1.staticflickr.com/5/4052/4352509985_5783b565ae.jpg]
Note to self: use private windows more. You didn't really need "howard the duck tits" as a search term Google will associate with you in the future...
EDIT: Woah, the "Unsee" button actually worked - the picture is gone!
-
[code]
private static uint lastAssignedID = 0;// [...]
public int AllocateID()
{
return lastAssignedID++;
}
[/code]
And not just for the return-statement-with-side-effects; it's also not thread-safe
-
In which case, it's really saying nothing at all, because how can the read or write of a single word-sized value not be atomic? The CPU kind of requires it to be.
The spec mentions "no larger than the native word size". An architecture that only has word-addressable memory can't guarantee that writes to something like a half-word are atomic and that they doesn't write bits other than those part of the half-word. A write would have to be a RMW (read word, bit-fiddle result into half of the word, write word).
Presumably it also prevents compiler writers from getting too clever with packing data into unaligned memory locations and such.
-
And not just for the return-statement-with-side-effects; it's also not thread-safeYeah, although to be fair it does the exact same thing as this:
[code]
public int AllocateID()
{
int newID = lastAssignedID;
lastAssignedID++;
return newID;
}
[/code]But in less code, and is just as readable (IMHO - 'course, I'm the one writing it, so obviously I'm biased in that regard)
As far as thread-safety, I'll admit it's been a while since I worried about thread safety - I work with a library that's already not thread-safe pretty much on the whole (so it's very rare that I can even think about making something multithreaded).
-
Given this hidiom started in C, you've got to be doubly careful because in C
accalia:
int q = (++i + 4) * (i++-1);isn't just hideous and ugly and stupid, its also undefined what the result is (up to and including segmentation faults, later untraceable off-by-one errors and nasal demons). It's one of the canonical DONT DO THIS of C programming (modifying a variable twice without a sequence point in between).
int q = (i + 5) * ((i += 2) - 3)
Filed under: it's worse than that he's dead Jim dead Jim dead
-
I have no idea which section of my terrible puns and bad code post you are referring to in your reply. Or if you really meant to reply to me and not the topic in general or someone else.
I'd assume I whooshed on a joke except there's not 20+ likes on your post
-
-
I'm advocating for changing every WARNING with ACHTUNG.
Naughty programmer! SPANK! SPANK!
-
Pretty sure that for the stereotypical programmer, getting spanked would be a positive incentive.
Since they aren't getting any from the "real world"
-
tar's posulate: For any standard idiom that exists in any programming language, there's always someone who thinks that they've managed to come up with a non-idiomatic approach which is somehow 'better' than the established way of doing things.
Goody, an excuse to link to Bournegol again
-
strike that... covered upthread
.... really? that was still a ninja..... whatever..... i tried to preserve original for the curious.
-
Seriously, it just reeks; much better to have the increments outside of the indexers.
At best this is a judgement call. Presumably the least error-prone way to organize the code is the most sensible...
yes it can be more error-prone if you're careless, but to me it's the most sensible way of doing it.
BZZT. Wrong. Thanks for playing though.
-
my problem isn't with the shortcut operator itself. it's the ability to embed it in other statements, and the reckless.abandon that some people do that to be "clever"
this doesn't bother me:
i++; var q = (i + 5) * i; i++;
but this does:var q = (++i + 4) * (i++-1);
so i forbid ++ and -- in projects i have control over. it's not that big a deal and it means you can't pull that shite on me.
lolwat. Sounds like throwing the baby out with the bathwater.
i would argue that operator overloading is it's own special evil. i do not like it, but i recognize that it is sometimes required for C++ programming.
there's a reason why i avoid C++ unless i have no other coice.
Except you can overload ++, --, and many other operators in C# as well.
-
-
Except you can overload ++, --, and many other operators in C# as well.
Surely you jest! Only those ebil C++ programmers would do something like that!
-
Surely you jest! Only those ebil C++ programmers would do something like that!
Let's just ban all language features—I'm not sure there's a single one which can't be misused...
Filed under: 11010110 10011011 11001101 01101100 101010010 11010001 11010011 110010011
-
Been there, done that. All that binary code is filled with what are essentially GOTOs or JMPs.... I can't tell you how many times I've wanted to murder a coworker for writing code like
11111111 11100000
I say ban everything but linear, sequential logic. Assholes.
-
While we're at it, let's just ban languages altogether. From henceforth we will communicate in semi-meaningful grunts, starting now:
ooog oog ug oog ook ook!
-
Ban everything! Including posting on WTDWTF!!!
BRB—banning self...
-
They're only atomic if you don't use the same memory twice in a statement.
i++
is not atomic in any language I know of. It's not even atomic in assembly. You need to use special instructions like "compare and set" to get atomic operations.
-
Integer'Last
If your array index doesn't give you strongly-typed bounds-checking in the first place, why would you even bother?
-
Also why the fuck are we here in the 21st century complaining about meaningless shit like this. Seriously, why isn't this shit just autotranslated into each person's preferred style on checkout or commit?
Or maybe there needs to a lang where all code is stored on disk as ast, and decompiled into your preferred dialect only during an edit session.
-
Also, all the code in this thread helped me refine my code highlighting css quite a bit. Now it looks like
code > br { display: none; } .cooked code, .reply code { font-size: inherit; line-height: inherit; padding: 0 0.5em; background: #002b36; color: #839496; } code.hljs { display: block; overflow-x: auto; line-height: 19px; } .hljs-comment, ...
which obviously makes everything look a lot more uniform.
BTW, @pjh, do you know if upstream picked up any of the css refinements you added before?