There is not one language called "assembly". There is at least one* assembly language for each different processor. I've done stuff in about half a dozen. If you're doing standard software development, it's almost certain that you won't miss it. If you're doing embedded software development, odds are much better that you'll find it useful. If you're writing a compiler back end, odds are that you will want to be an expert in the target assembly language. If you're interested, you may as well learn one to get the feel. You don't have to learn to use it well.
Also, I'm going to ask some of you to get off my lawn. When I was young, I had a TRS-80 with a Z80 processor, and I could do almost anything in Z80 assembler. I knew what the Z80 was going to do at any given time. I could figure out how long any individual operation was likely to take. More modern processors do things in a much more complicated manner, with memory speed depending on the caches and even the order of execution depending on what's going on inside the CPU. (My first experience in this was assembly for the CDC 6600.) The fundamental simplicity and ability to comprehend what the CPU is doing no longer exists for modern CPUs.
*In some cases, I ran into different assemblers using different names for the instructions. Translating between the two was mechanical, but you couldn't use a program for one for another. Also, some assemblers had more complicated operations, which might specify where the assembled output was put, or even have macros, and those differed. In this sense, there might be several assembly languages for one CPU.
"tail recursion" is a technique of making it easy to convert recursion into iteration. If the last statement in function f(x) is "return f(--x);", you're just running the function again with a different parameter, and that can trivially become a loop.
Do that, and you will find how the specific version of the specific compiler you are using does it in that context. If you do it in gcc, you don't know what clang will do. That's why we have standards: so we can write code that will work in different compilers and have it do what we want.
In which case, it's still undefined, since "C" and "C++" will be in two distinct places in memory that have no connection, and comparisons are undefined. (There have been weird memory access systems that justify this, I believe.) In practice on modern computers, there will be two numeric memory addresses, and no way to determine beforehand which is higher.
As TsuruchBrian said, it is possible to have existing code so badly written that nobody's going to figure it out, and that's possible in any general-purpose computer language. However, given a reasonably well-written C++ codebase, someone who is good at C++ will not have excessive difficult in maintaining it. We know this from experience, We have a large C++ codebase, reasonably well-written considering its history, and when we hire people with C++ experience who have never seen the codebase, the big problem with familiarization is the complexity of the problems it solves.
Problems can be simple of complex. If they're simple, it doesn't matter much what language the solution is in. When they're complex, you want a language that handles complexity well, typically by creating abstractions to keep the complexity of any given piece manageable. C++ is very good at that. C is not nearly as good at it. Given a complex problem, the C++ solution will normally be considerably shorter and much easier for someone skilled in the language to understand, partially or in toto, than a C solution.
In K&R C, there was no clear way to tell what would happen with some constructs, but didn't have undefined behavior in the sense of a C Standard.
The first C Standard was in 1989. It was an ANSI standard, and became an ISO standard in 1990. According to the Standard, the behavior of "C++ >/; C" is undefined. More practically, there are several operations there (two fetch Cs, one evaluation, one increment, and one comparison) and only a partial order. It will indeed be translated into assembly or machine code that will do something predictable from the assembly or machine code (or maybe not (there are exceptions here), but the Standard does not define what assembly or machine code should be written, or what it should do.
And what is expected behavior? Side effects in the order of evaluation, or side effects at the end? I can easily justify either.
In this case, a variable is being read (both C and C++) and written (the result of C++) between sequence points, which is C's idea of "while".
No. You're confusing order of evaluation with order of side effects. The two are not connected. When the comparison takes place is unrelated to when the increment takes place. The value of s++ is evaluated before the comparison, but all we know about the increments is that they have to take place sometime before the next sequence point. You also mean lower precedence, not higher precedence.
Doubtless it's undefined because different machines in common use would have done it differently, and so specifying behavior would have slowed computation down. One design goal of C was to prioritize execution speed of its output. Similarly, signed arithmetic overflow is undefined, because some processors threw some sort of exception or signal and some just went with the overflow. If the Standard specified what happened, one of those groups was going to be unable to do signed arithmetic without checking things. Personally, I think they should have defined possible behaviors and left them to be unspecified or implementation-defined (implementation-defined means the behavior has to be documented, while unspecified means it has to do something reasonable but the programmer can't count on any particular behavior).
You're saying what might happen in practice. The Standard does not address this, so the program is not conforming C or C++, and the Standard has nothing to say about what happens. Anything is in accordance.
I don't know C99 as precisely as C90, but at least in C90 the statement is undefined, and causes the whole program to be undefined. The result of the comparison can be true, false, or Tuesday, all according to the standard.
In C++ > C, the increment happens between the previous and the next sequence points. It's exactly because > does not cause a new sequence point that there is no sequence point between C++ and C, and so by 6.5.2.4, the increment takes place at roughly the same time as the comparison, possibly before and possibly after.
From my point of view in that situation, there's really no difference between the United States government and five guys with guns. I can't fight off either. I'm going to get killed. Given that, there's fewer people in the government that want to shoot me personally, and I have some influence over government actions.
edx93 said the driver ran the red. Drivers have no compulsion to turn right on red, or any right-of-way. If you want to turn on red, it's your job to avoid collisions.
What about times when I don't want to be THAT much of an obstacle on the road to obey the speed limit? We're all safer if we all move predictably and stay with the flow of traffic.
Of course, there was the time when the family (including baby) appeared from behind the bus, where my wife had no way to see them. Had we been one lane over, I don't see how we could have missed them. They looked at us like we should normally stop at green lights in case pedestrians appear.
Heinlein didn't hesitate to put things he believed in into his stories directly. Specifically labeling something as written by a character suggests that it wasn't necessarily Heinlein's mindset.
Given no government, any private entity has the legal power to destroy you. Whether it's ten guys with guns or an all-encompassing monster matters little when the gun is pointed at your head.
When something is a matter of engineering, and not physically impossible, I like to be a little slow before calling it impossible. First, I want to check and see if anyone's actually doing it.
And, of course, trucks could be driving themselves under certain circumstances over the next several years.
When I was young, it was possible for most white men of low skill but good work ethic to make a decent living for their families. That's pretty much over. Now that I'm old, I work in manufacturing, and when I'm on the shop floor the odds are I can't see another human being. One will pop by from time to time to do something with the computer-controlled machinery.
There is not one language called "assembly". There is at least one* assembly language for each different processor. I've done stuff in about half a dozen. If you're doing standard software development, it's almost certain that you won't miss it. If you're doing embedded software development, odds are much better that you'll find it useful. If you're writing a compiler back end, odds are that you will want to be an expert in the target assembly language. If you're interested, you may as well learn one to get the feel. You don't have to learn to use it well.
Also, I'm going to ask some of you to get off my lawn. When I was young, I had a TRS-80 with a Z80 processor, and I could do almost anything in Z80 assembler. I knew what the Z80 was going to do at any given time. I could figure out how long any individual operation was likely to take. More modern processors do things in a much more complicated manner, with memory speed depending on the caches and even the order of execution depending on what's going on inside the CPU. (My first experience in this was assembly for the CDC 6600.) The fundamental simplicity and ability to comprehend what the CPU is doing no longer exists for modern CPUs.
*In some cases, I ran into different assemblers using different names for the instructions. Translating between the two was mechanical, but you couldn't use a program for one for another. Also, some assemblers had more complicated operations, which might specify where the assembled output was put, or even have macros, and those differed. In this sense, there might be several assembly languages for one CPU.
"tail recursion" is a technique of making it easy to convert recursion into iteration. If the last statement in function f(x) is "return f(--x);", you're just running the function again with a different parameter, and that can trivially become a loop.
You had a needle.
I had to raise my own butterflies.
Do that, and you will find how the specific version of the specific compiler you are using does it in that context. If you do it in gcc, you don't know what clang will do. That's why we have standards: so we can write code that will work in different compilers and have it do what we want.
In which case, it's still undefined, since "C" and "C++" will be in two distinct places in memory that have no connection, and comparisons are undefined. (There have been weird memory access systems that justify this, I believe.) In practice on modern computers, there will be two numeric memory addresses, and no way to determine beforehand which is higher.
As TsuruchBrian said, it is possible to have existing code so badly written that nobody's going to figure it out, and that's possible in any general-purpose computer language. However, given a reasonably well-written C++ codebase, someone who is good at C++ will not have excessive difficult in maintaining it. We know this from experience, We have a large C++ codebase, reasonably well-written considering its history, and when we hire people with C++ experience who have never seen the codebase, the big problem with familiarization is the complexity of the problems it solves.
Problems can be simple of complex. If they're simple, it doesn't matter much what language the solution is in. When they're complex, you want a language that handles complexity well, typically by creating abstractions to keep the complexity of any given piece manageable. C++ is very good at that. C is not nearly as good at it. Given a complex problem, the C++ solution will normally be considerably shorter and much easier for someone skilled in the language to understand, partially or in toto, than a C solution.
There is nothing in any of the Standards mentioned that supports your statement. Other languages may well do it this way, but not C or C++.
In K&R C, there was no clear way to tell what would happen with some constructs, but didn't have undefined behavior in the sense of a C Standard.
The first C Standard was in 1989. It was an ANSI standard, and became an ISO standard in 1990. According to the Standard, the behavior of "C++ >/; C" is undefined. More practically, there are several operations there (two fetch Cs, one evaluation, one increment, and one comparison) and only a partial order. It will indeed be translated into assembly or machine code that will do something predictable from the assembly or machine code (or maybe not (there are exceptions here), but the Standard does not define what assembly or machine code should be written, or what it should do.
And what is expected behavior? Side effects in the order of evaluation, or side effects at the end? I can easily justify either.
In this case, a variable is being read (both C and C++) and written (the result of C++) between sequence points, which is C's idea of "while".
No. You're confusing order of evaluation with order of side effects. The two are not connected. When the comparison takes place is unrelated to when the increment takes place. The value of s++ is evaluated before the comparison, but all we know about the increments is that they have to take place sometime before the next sequence point. You also mean lower precedence, not higher precedence.
Doubtless it's undefined because different machines in common use would have done it differently, and so specifying behavior would have slowed computation down. One design goal of C was to prioritize execution speed of its output. Similarly, signed arithmetic overflow is undefined, because some processors threw some sort of exception or signal and some just went with the overflow. If the Standard specified what happened, one of those groups was going to be unable to do signed arithmetic without checking things. Personally, I think they should have defined possible behaviors and left them to be unspecified or implementation-defined (implementation-defined means the behavior has to be documented, while unspecified means it has to do something reasonable but the programmer can't count on any particular behavior).
You're saying what might happen in practice. The Standard does not address this, so the program is not conforming C or C++, and the Standard has nothing to say about what happens. Anything is in accordance.
I don't know C99 as precisely as C90, but at least in C90 the statement is undefined, and causes the whole program to be undefined. The result of the comparison can be true, false, or Tuesday, all according to the standard.
In C++ > C, the increment happens between the previous and the next sequence points. It's exactly because > does not cause a new sequence point that there is no sequence point between C++ and C, and so by 6.5.2.4, the increment takes place at roughly the same time as the comparison, possibly before and possibly after.
In what way is server-side formatting different from client-side? In neither case is the final product, in most cases, be what the designer designed.
Why is a protocol defective simply because it doesn't do what you want?
The scientists seem to agree on this. Everywhere scientific I check out, there's general agreement. Where does one find evidence of disagreement?
From my point of view in that situation, there's really no difference between the United States government and five guys with guns. I can't fight off either. I'm going to get killed. Given that, there's fewer people in the government that want to shoot me personally, and I have some influence over government actions.
edx93 said the driver ran the red. Drivers have no compulsion to turn right on red, or any right-of-way. If you want to turn on red, it's your job to avoid collisions.
Pedestrians on smartphones (or just being really dumb) are a hazard to drivers. You can get PTSD from killing a pedestrian.
What about times when I don't want to be THAT much of an obstacle on the road to obey the speed limit? We're all safer if we all move predictably and stay with the flow of traffic.
Of course, there was the time when the family (including baby) appeared from behind the bus, where my wife had no way to see them. Had we been one lane over, I don't see how we could have missed them. They looked at us like we should normally stop at green lights in case pedestrians appear.
Heinlein didn't hesitate to put things he believed in into his stories directly. Specifically labeling something as written by a character suggests that it wasn't necessarily Heinlein's mindset.
Given no government, any private entity has the legal power to destroy you. Whether it's ten guys with guns or an all-encompassing monster matters little when the gun is pointed at your head.
When something is a matter of engineering, and not physically impossible, I like to be a little slow before calling it impossible. First, I want to check and see if anyone's actually doing it.
And, of course, trucks could be driving themselves under certain circumstances over the next several years.
When I was young, it was possible for most white men of low skill but good work ethic to make a decent living for their families. That's pretty much over. Now that I'm old, I work in manufacturing, and when I'm on the shop floor the odds are I can't see another human being. One will pop by from time to time to do something with the computer-controlled machinery.
Due to allergies*, I demand a certified leopard-free viewing area.
*Well, not technically allergies, but leopards can cause me to have impaired health.