Earlier quoted context omitted.
int pop_int () { int x = *stack; --stack; return x; } void push_int(int x) { ++stack; *stack = x; } Genunine questions: - Is this worse? - How does the state get inconsistent?
For one it’s three and two lines for what is two logical operations. I assume the “inconsistent state” is the time between the lines where the stack is not truly in the right state-many people prefer to preserve their invariants as much as possible.
Essential C (2003) [pdf]
51–60 of 84 posts
Re: Essential C (2003) [pdf]
#52Earlier quoted context omitted.
For one it’s three and two lines for what is two logical operations. I assume the “inconsistent state” is the time between the lines where the stack is not truly in the right state-many people prefer to preserve their invariants as much as possible.
it will produce indistinguishable assembly language, no?
Re: Essential C (2003) [pdf]
#53I never really got to a point of learning Haskell or Lisp up until recently, it was always this --- I can do everything with C/C++/Java/Python and I could. But the thing is it is only after learning lisp that I really got the hang of thinking in top down manner(recursively), or for that matter it took Haskell to teach me composition intuitively, which then could be extended to my main language(C++). I understand that syntax doesn't matter much, but fwiw I still think in terms of lisp syntax when writing recursive code in C++/C. So yeah, take that for you will.
Re: Essential C (2003) [pdf]
#54Earlier quoted context omitted.
it will produce indistinguishable assembly language, no?
The use of that construct is mainly a stylistic choice. On any compiler from this millennium there should be no difference in the code that it produces.
Relying on post-increment? Make sure it's a one line block that is totally unbraced with only single letter variable names if you do it because otherwise it's just faux-macho C and that's /weak/.
Re: Essential C (2003) [pdf]
#55Earlier quoted context omitted.
The use of that construct is mainly a stylistic choice. On any compiler from this millennium there should be no difference in the code that it produces.
Yep so if we're going with style I'm very happy with the functions dashed off there. Nobody will confuse those even when very, very tired (similar effect on the brain to being drunk). There is zero difference in the generated output. Calling those functions tells you exactly what they are and what they do. Vertical space is not an issue at all with 3 line functions. Relying on post-increment? Make sure it's a one lin…
I think you're projecting. The point being made was that when you're writing a simple stack (as you often might do in C, since the standard library and the language itself conspire against providing you one) and you don't have the overhead to write multiple functions to wrap it up (vertical space is an issue when you make more than one of these–trust me, I used to write Java and every thing about it was just a papercut in verbosity), the post- and pre-increment versions are concise, idiomatic, and–to be honest–more clear simply because they use the operators in the way that they are meant to be used. I can glance at them and see, OK, this one gives me whatever the stack is pointing to and then makes it point to the next element; this one first moves the pointer to the next element (which is free) and sets it. All in one line. There's nothing to show off here, this is just how you write C; those operators exist for exactly this purpose (and IMO single letter variable names are generally only a good idea in the smallest of scopes, and I personally use braces even when optional).
Re: Essential C (2003) [pdf]
#56Earlier quoted context omitted.
Imagine operating on something like a stack. x = *stack--; // pop 'x' off of the stack *++stack = y; // push 'y' onto the stack This way is simple, direct, and it avoids inconsistent state.
I don't see how this proves the point. For someone who doesn't have the operator precedence rules memorized, it isn't clear whether the above code means this: x = *stack; stack--; or this: stack--; x = *stack; Combining those two operations into one line is a trade-off I will never agree with. And I'm a fan of C myself: https://gist.github.com/cellularmitosis/3327379b151445c602ad... https://gist.github.com/cellularmi…
Re: Essential C (2003) [pdf]
#57Re: Essential C (2003) [pdf]
#58Re: Essential C (2003) [pdf]
#59Earlier quoted context omitted.
Imagine operating on something like a stack. x = *stack--; // pop 'x' off of the stack *++stack = y; // push 'y' onto the stack This way is simple, direct, and it avoids inconsistent state.
I don't see how this proves the point. For someone who doesn't have the operator precedence rules memorized, it isn't clear whether the above code means this: x = *stack; stack--; or this: stack--; x = *stack; Combining those two operations into one line is a trade-off I will never agree with. And I'm a fan of C myself: https://gist.github.com/cellularmitosis/3327379b151445c602ad... https://gist.github.com/cellularmi…
It's about performance, or thread safety, or anything like that; it's about having a coherent mental model of the code. A statement should, if possible, represent a single, complete operation. Invariants should not be violated by a statement, with respect to its environment. (This more true for 'push' than 'pop'.) One way of solving that is to bundle the 'push' and 'pop' operations up into functions; someone else in this thread did that. But why bother with the mental overhead of a function call when you could just represent the operation directly? To be sure, there are cases where the abstraction is warranted, but a two~three-line stack operation isn't abstraction, it's just indirection.
> For someone who doesn't have the operator precedence rules memorized, it isn't clear whether the above code means [snipped] or [snipped]
> The two-liner [...] requires less knowledge of operator precedence rules
It's not operator precedence—that's a separate issue; despite having implemented c operator precedence, I don't know all of them by heart—but simply behaviour of pre- and post-increment/decrement operations. It's even mnemonic—when the increment symbol goes before the thing being incremented, the increment happens first; else after—but even if not, it's a fairly basic language feature.
Even beyond that, though, it's an idiom. Code is not written in a vacuum. Patterns of pre- and post-increment fall into common use over time and become part of an established lexicon which is not specified anywhere. Natural language works the same way. Nothing wrong with that.