syzygy wrote:bob wrote:syzygy wrote:bob wrote:BTW the semantics are anything BUT "clearly spelled out in the standards." I don't consider "undefined behavior" to be "clearly spelled out."
The whole point of UB is that the semantics of a C program is undefined once it exhibits any kind of UB.
Particularly when things like signed integer overflow are clearly defined in the x86 specs.
Very relevant for the semantics of an x86 assembly program, but completely irrelevant for the semantics of a C program.
This distinction is important. Maybe I should repeat it.
Very relevant for the semantics of an x86 assembly program, but completely irrelevant for the semantics of a C program.
There.
Fine. Yet I am writing C on a compiler written for the X86, where I expect the program to run on x86, so I don't expect oddball things to break that work perfectly ON x86. And the compiler COULD do exactly that. It SHOULD do exactly that. But a few keep repeating the "but undefined behavior means anything can happen" which is actually a false statement much of the time.
If it is only a false statement "most of the time", then obviously it is a very true statement. You don't want to have a program that works as intended only "most of the time", do you?
A accept this kind of nonsense all the time. On a Cray, an int is 64 bits, on a pc, it is 32. On a Cray, a long is 64 bits. On my linux box on x86_64, a long is 64. On windows a long is 32. So there are already issues, and I deal with them without getting lost. I generally know the hardware characteristics of the platforms I run on, I know what their strengths are (vectors on a Cray) and when useful, I write things that will run on that machine efficiently. If it doesn't run so efficiently elsewhere, I figure out a way to compensate. IE we JUST got a popcnt instruction on X86. But I have been doing a popcnt operation since Crafty version 1.0 in 1994. I like having that level of control.
What a C99 compiler SHOULD do is defined by the standard.
Unfortunately the C99 standard has more holes in it than a wheel of swiss cheese. Undefined behavior, implementation-dependent behavior, etc. A standard is usually "specific". I can't imagine any of those undefined behaviors or "do whatever you want" options in the space shuttle specs, for example.
If you need a compiler that guarantees more than C99 (or some other C standard), then it would be a good idea to find a compiler (or a set of compiler options) that provides this guarantee.
Certainly integer overflow on any hardware from the last 30 years, excepting for Univac which has been dead for about that long, is not "undefined at all.
So what is then? Signed overflow wraps? You have already explained that that is not what you want in the case of x * 2 / 2.
It wraps in ALL cases. The only question is, does it wrap at 32 or more bits? I'd like to see it do the best the hardware can offer. I suppose C COULD just use 16 bit values on x86, since that is all the 286 can do. But there is more in the hardware.
But the very basic mistake you keep making is confusing x86 semantics with C semantics.
A C programmer should only be concerned with C semantics. He can rely on what is defined by the C standard. He can not rely on anything else (unless he restricts himself to a particular compiler that offers additional guarantees). The contract between the C programmer and the C compiler is the C standard.
For a naive or sloppy programmer, that is likely true. However some of us want as much as we can get. For example, BSF/BSR as soon as they became available on X86, rather than waiting a few years for the compiler guys to realize that was useful and adding some non-portable intrinsics. I suppose I should just find a version of gcc that does what I like, and save that source forever, before the authors "improve" it to the point where I consider it unusable. I've never been shy about using asm in a C program when the compiler didn't give me a way to access some hardware feature that C had no semantics for. So trying to hide behind this "I don't care about the underlying machine" sounds like something Java programmers say over and over while breathing incense. I DO care about the underlying machine.
Check this out from the Wiki:
wiki wrote:
n computing, C (/ˈsiː/, as in the letter C) is a general-purpose programming language initially developed by Dennis Ritchie between 1969 and 1973 at AT&T Bell Labs.[4] Like most imperative languages in the ALGOL tradition, C has facilities for structured programming and allows lexical variable scope and recursion, while a static type system prevents many unintended operations. Its design provides constructs that map efficiently to typical machine instructions, and therefore it has found lasting use in applications that had formerly been coded in assembly language, most notably system software like the Unix computer operating system.
"we" never wanted C to get in the way of getting to the hardware, we wanted it to help. You seem to be on the opposite side of the street, continually repeating over and over "it is about the abstract machine not the underlying hardware." I've been programming in C far longer than you, long enough to remember when the above was the primary reason for the popularity of the language. You probably dislike casts because they can get you into trouble. I like them because while they can get you in trouble if you are sloppy or don't know what you are doing, they can save some effort if you use them correctly.
A C compiler for x86 is concerned with the x86 semantics. The compiler relies on what is guaranteed by Intel's manuals. The contract between the C compiler and the x86 architecture is the Intel manual.
I realize that there are those of us in software development that have reasonable interpretations of how things SHOULD be done, and there are those that lather up when they see things that mention "undefined behavior" in the spec.
You really should not be so deluded as to believe that all your "adveraries" in this thread have no good idea of what a direct mapping from C
syntax to x86 assembly could look like. We all understand this very very well. But we, adversaries, are able to think at a level abstract enough that we can distinguish between this naive machine model of C and the more mathematically defined promises provided by the C standard.
See the quote from the Wiki. Many of us do NOT agree with you. But keep repeating "it is about the standard" over and over. Perhaps one day it will be.