system-dependent behaviour
Hi, Just want to confirm that the following statements is 'dangerous', in the sense that it's system dependant. I recall to read somewhere there're additional case where this can happen, such as dofun(s, s++). Any insight on why it happens is highly appreciated. Here's the program: int main(void) { int s=3; printf("s=%i,s=%i,s=%i\n",s,s++,s--); return 0; } For the result, I got s=3,s=2,s=3 on SuSE 9.3, but on a Solaris machine, I got s=3,s=3,s=4. Regards, Verdi -- 5 GB Mailbox, 50 FreeSMS http://www.gmx.net/de/go/promail +++ GMX - die erste Adresse für Mail, Message, More +++
On Saturday 10 September 2005 08:35, Verdi March wrote:
Hi,
Just want to confirm that the following statements is 'dangerous', in the sense that it's system dependant. I recall to read somewhere there're additional case where this can happen, such as dofun(s, s++).
Any insight on why it happens is highly appreciated.
Here's the program: int main(void) { int s=3; printf("s=%i,s=%i,s=%i\n",s,s++,s--); return 0; }
For the result, I got s=3,s=2,s=3 on SuSE 9.3, but on a Solaris machine, I got s=3,s=3,s=4.
The rule is: you can only modify a variable once between two sequence points. The reason is that between two sequence points, the compiler is free to do things in any order. This is why you can't do things like x=x++ This isn't system dependent, it is undefined behaviour. Which translated into English means that the compiler is free to do anything at all (I believe the classic example is that it can cause bats to fly out of your nose) Your example is equivalent to this, because you are modifying s twice between two sequence points. Not allowed. You probably wanted something like printf("s=%i,s=%i,s=%i\n",s,s+1,s-1); Remember that the post/prefix operators ++ and -- actually modifies the variable
Anders, Verdi, On Saturday 10 September 2005 00:39, Anders Johansson wrote:
On Saturday 10 September 2005 08:35, Verdi March wrote:
Hi,
Just want to confirm that the following statements is 'dangerous', in the sense that it's system dependant. I recall to read somewhere there're additional case where this can happen, such as dofun(s, s++).
Any insight on why it happens is highly appreciated.
Here's the program: int main(void) { int s=3; printf("s=%i,s=%i,s=%i\n",s,s++,s--); return 0; }
For the result, I got s=3,s=2,s=3 on SuSE 9.3, but on a Solaris machine, I got s=3,s=3,s=4.
...
Your example is equivalent to this, because you are modifying s twice between two sequence points. Not allowed. You probably wanted something like
printf("s=%i,s=%i,s=%i\n",s,s+1,s-1);
Perhaps. Verdi used _post_ -increment and -decrement, so apart from the ambiguity introduced by the compiler's freedom to order the evaluation of the function arguments any way it wishes, his code tried to say he wanted the value of 's' _before_ incrementing or decrementing 's', not after. One might suspect he wanted this: printf("s=%i,s=%i,s=%i\n", s, s, s + 1);
...
Randall Schulz
Hi,
Just want to confirm that the following statements is 'dangerous', in the sense that it's system dependant. I recall to read somewhere there're additional case where this can happen, such as dofun(s, s++).
Any insight on why it happens is highly appreciated.
Here's the program: int main(void) { int s=3; printf("s=%i,s=%i,s=%i\n",s,s++,s--); return 0; }
For the result, I got s=3,s=2,s=3 on SuSE 9.3, but on a Solaris machine, I got s=3,s=3,s=4. Just to add to Anders comments. According to the ANSI 89 standard, this is an unspecified operation. The issue here is when the postincrement operator is applied to s. C pushes variables from the last to the first because it may have an unknown number of parameters. So, the s-- is pushed first, hence the
On Sat, 10 Sep 2005 08:35:12 +0200 (MEST) "Verdi March" <cincaipatron@gmx.net> wrote: third parameter is evaluated as 3. In this case, gcc applies the postdecrement immediately after it pushes the parm on the stack. The second parameter then evaluates to 2 because s now contains 2. Again, gcc increments, resulting in the first parameter as 3. ANSI 3.3.2.2. Another similar issue is i = ++i + 1; The above is an "undefined" operation. (ANSI 3.3). -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
On Saturday 10 September 2005 17:47, Jerry Feldman wrote:
Just to add to Anders comments. According to the ANSI 89 standard, this is an unspecified operation. The issue here is when the postincrement operator is applied to s. C pushes variables from the last to the first because it may have an unknown number of parameters.
This is a completely unwarranted assumption. This may be the way any one compiler works (and it does make sense), but according to 6.5.2.2 of the 1999 standard "The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call" So while I'm sure you're right about any one compiler, it is very wrong to say that C does it, and suicidal to rely on it
On Sunday 11 September 2005 03:39, Anders Johansson wrote:
On Saturday 10 September 2005 17:47, Jerry Feldman wrote:
Just to add to Anders comments. According to the ANSI 89 standard, this is an unspecified operation. The issue here is when the postincrement operator is applied to s. C pushes variables from the last to the first because it may have an unknown number of parameters.
This is a completely unwarranted assumption. This may be the way any one compiler works (and it does make sense), but according to 6.5.2.2 of the 1999 standard
"The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call"
So while I'm sure you're right about any one compiler, it is very wrong to say that C does it, and suicidal to rely on it
I agree; you need to look at your own compilerS. I add the S because linking object code from two different languages can get one into a lot of trouble if they don't obey the same rules. Also one should note that some compilers pass addresses (best in my opinion) while others pass "values". (Values? C passes values sometimes and addresses if it feels like it, so be careful.) And some compilers pass 'hidden' information. So: Why in hell would anybody want to pass something as dumb as s++ ? Us old farts use K.I.S.S. Regards, Colin
Colin, On Saturday 10 September 2005 18:38, Colin Carter wrote:
...
So while I'm sure you're right about any one compiler, it is very wrong to say that C does it, and suicidal to rely on it
I agree; you need to look at your own compilerS.
Wrong. You need to code to the standard so your code is immune to changes in the compiler or the environment in which it is to be run. When people use experiments with particular compilers to learn the language, they set themselves up for unpredictable behavior in the future.
I add the S because linking object code from two different languages can get one into a lot of trouble if they don't obey the same rules. Also one should note that some compilers pass addresses (best in my opinion) while others pass "values". (Values? C passes values sometimes and addresses if it feels like it, so be careful.)
You have got to be kidding. The language is quite clear about the distinctions between values, pointers and references and which is used when and while there are many areas where the compiler (writer) has discretion about its exact behavior, there's no such discretion (no "feels like it") when it comes to parameter passing and whether values, pointers or references are what's passed. That's a big part of what strong typing is about, after all. While no language can be used without understanding, C and C++ are more demanding than most in their subtleties. So be it.
...
Colin
Randall Schulz
Colin,
On Saturday 10 September 2005 18:38, Colin Carter wrote:
...
So while I'm sure you're right about any one compiler, it is very wrong to say that C does it, and suicidal to rely on it
I agree; you need to look at your own compilerS.
Wrong. You need to code to the standard so your code is immune to changes in the compiler or the environment in which it is to be run. Randall, You cannot always code to 'the standard'. For example, FORTRAN (a very well established language) had a standard of
On Sunday 11 September 2005 12:09, Randall R Schulz wrote: pushing the first argument first, and always by address - simple idea. The other languages followed suit. Then came C For other languages to mix it with C the compilers had to have 'fiddles' inserted into the compilers. e.g. C TYPE routine call Eventually FORTRAN changed its standards to try to assist with compatability. Which means that old FORTRAN code would no execute. And as for ME being 'non-standard', I would like to point out that I developed a very large program over four years of work, on a PC. Then mailed it (yes, we had 'email' years ago) to a reduced instruction set VAX mainframe and it worked the first run. (Code still took 6 hours to execute.)
I add the S because linking object code from two different languages can get one into a lot of trouble if they don't obey the same rules. Also one should note that some compilers pass addresses (best in my opinion) while others pass "values". (Values? C passes values sometimes and addresses if it feels like it, so be careful.)
You have got to be kidding. The language is quite clear about the distinctions between values, pointers and references and which is used when and while there are many areas where the compiler (writer) has discretion about its exact behavior, there's no such discretion (no "feels like it") when it comes to parameter passing and whether values, pointers or references are what's passed. That's a big part of what strong typing is about, after all.
You know, you use jargon like "typing", as thought it is a new idea. Us old guys just considered it an intrinsic part of the process; much like we structured our code years before the academics invented the word "structured design" to prevent kids from making spaghetti code. (Twit the language PASCAL, at first without a goto.)
While no language can be used without understanding, C and C++ are more demanding than most in their subtleties. So be it.
I suggest that you replace the word 'demanding' with 'complicated and messy'.
...
Colin
Randall Schulz
Colin
And as for ME being 'non-standard', I would like to point out that I developed a very large program over four years of work, on a PC. Then mailed it (yes, we had 'email' years ago) to a reduced instruction set VAX mainframe and it worked the first run. (Code still took 6 hours to execute.) VAX-C or DEC-C? In my experience I have been dealing with a number of different
On Sun, 11 Sep 2005 17:26:28 +1000 Colin Carter <colincarter@exemail.com.au> wrote: platforms (and 32-bit to 64-bit and big-endian to little-endian) for years. I always recommend trying to code to the standards, but there are cases where it is not possible. -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
On Sunday 11 September 2005 23:40, Jerry Feldman wrote:
On Sun, 11 Sep 2005 17:26:28 +1000
Colin Carter <colincarter@exemail.com.au> wrote:
And as for ME being 'non-standard', I would like to point out that I developed a very large program over four years of work, on a PC. Then mailed it (yes, we had 'email' years ago) to a reduced instruction set VAX mainframe and it worked the first run. (Code still took 6 hours to execute.)
VAX-C or DEC-C? In my experience I have been dealing with a number of different platforms (and 32-bit to 64-bit and big-endian to little-endian) for years. I always recommend trying to code to the standards, but there are cases where it is not possible. FORTRAN :-) VAX I think, but it was ten years ago, so I can't remember for sure. Good night, Regards, Colin
FORTRAN :-) VAX I think, but it was ten years ago, so I can't remember for sure. Good night, Pleasant dreams Colin. Please don't stay up counting bits :-) VAX Fortran was fairly standard with some extensions. Stan Whitlow was
On Mon, 12 Sep 2005 01:11:41 +1000 Colin Carter <colincarter@exemail.com.au> wrote: the Fortran GURU at DEC 10 years ago, and I believe he was transferred to Intel. VAX-C was a DEC dialect of C and not very standard. DECC was a totally new product written for Open VMS/Alpha, Windows NT Alpha and Tru64 Unix. -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
Colin, On Sunday 11 September 2005 00:26, Colin Carter wrote:
On Sunday 11 September 2005 12:09, Randall R Schulz wrote:
Colin,
...
Wrong. You need to code to the standard so your code is immune to changes in the compiler or the environment in which it is to be run.
Randall, You cannot always code to 'the standard'.
Sorry, but again you're wrong. You may have to work around compiler problems and idiosyncracies (more so in the past than now, but still an issue), but that's the exception and one of the reasons conditional compilation is necessary in C/C++.
For example, FORTRAN (a very well established language) had a standard of pushing the first argument first, and always by address - simple idea. The other languages followed suit.
If you're going to keep thinking in language implementation terms instead of in terms of the abstractions in which the language is defined, you're going to remain confused.
Then came C For other languages to mix it with C the compilers had to have 'fiddles' inserted into the compilers. e.g. C TYPE routine call Eventually FORTRAN changed its standards to try to assist with compatability. Which means that old FORTRAN code would no execute.
"Fiddles?" You really seem to think that compilers (or their writers) are capricious. Besides, I don't think we're talking about FORTRAN here.
And as for ME being 'non-standard', I would like to point out that I developed a very large program over four years of work, on a PC. Then mailed it (yes, we had 'email' years ago) to a reduced instruction set VAX mainframe and it worked the first run. (Code still took 6 hours to execute.)
I don't know what ME is. And drop the "older than thou" routine. Not everyone here is newbie.
...
You have got to be kidding. The language is quite clear about the distinctions between values, pointers and references and which is used when and while there are many areas where the compiler (writer) has discretion about its exact behavior, there's no such discretion (no "feels like it") when it comes to parameter passing and whether values, pointers or references are what's passed. That's a big part of what strong typing is about, after all.
You know, you use jargon like "typing", as thought it is a new idea. Us old guys just considered it an intrinsic part of the process; much like we structured our code years before the academics invented the word "structured design" to prevent kids from making spaghetti code. (Twit the language PASCAL, at first without a goto.)
You don't even know who you're talking to. And you clearly don't know what you're talking about.
While no language can be used without understanding, C and C++ are more demanding than most in their subtleties. So be it.
I suggest that you replace the word 'demanding' with 'complicated and messy'.
So be it. If you can't handle it, choose a different language.
Colin
Randall Schulz
Sorry, but again you're wrong. You may have to work around compiler problems and idiosyncracies (more so in the past than now, but still an issue), but that's the exception and one of the reasons conditional compilation is necessary in C/C++. IMHO, anytime code is written it should be written to the existing standards, but I have also seen a number of cases where a violation of
On Sun, 11 Sep 2005 07:37:23 -0700 Randall R Schulz <rschulz@sonic.net> wrote: the standard may be necessary. This generally makes code unportable. Today, portability is very important because one is likely to see many different platforms running the same code in the same data center, so it certainly behooves us to write portable, standards compliant code. -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
On Sat, 10 Sep 2005 19:09:52 -0700 Randall R Schulz <rschulz@sonic.net> wrote:
While no language can be used without understanding, C and C++ are more demanding than most in their subtleties. So be it. Very true. This is because C was designed as an implementation language not a high level language. It gives the programmer much more power than most high level languages. -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
On Sunday 11 September 2005 03:38, Colin Carter wrote:
On Sunday 11 September 2005 03:39, Anders Johansson wrote:
On Saturday 10 September 2005 17:47, Jerry Feldman wrote:
Just to add to Anders comments. According to the ANSI 89 standard, this is an unspecified operation. The issue here is when the postincrement operator is applied to s. C pushes variables from the last to the first because it may have an unknown number of parameters.
This is a completely unwarranted assumption. This may be the way any one compiler works (and it does make sense), but according to 6.5.2.2 of the 1999 standard
"The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call"
So while I'm sure you're right about any one compiler, it is very wrong to say that C does it, and suicidal to rely on it
I agree; you need to look at your own compilerS.
That's not what I said (or at least not what I meant :) You need to look at your own code, and make sure you only code according to standards.
(Values? C passes values sometimes and addresses if it feels like it, so be careful.)
Parameters in C are always passed by value. If you want to have call by reference, you need to do that explicitly, by passing a pointer (in which case it's still call by value, since you're passing the value of the pointer) The exception is when you have an array or function as parameter, in which case the pointer to it is passed, but this is well defined, not willy nilly The relevant sections are 6.5.2.2 and 6.7.5.3 in the 1999 standard
So: Why in hell would anybody want to pass something as dumb as s++ ?
Well, it's not s++ that's passed, it's s. Having 's++' in the parameter list is just telling the compiler that s is to be incremented by one immediately after its value has been used in the function call. This can be useful as a hint to the compiler, so it can increment s while it's still held in a register. If you have s=s+1; on the next line, a clever compiler might still be able to detect it and rearrange things, but with the postfix notation it's much easier. Especially in tight inner loops, small tricks like this can have noticeable payoffs
On Sunday 11 September 2005 12:25, Anders Johansson wrote:
On Sunday 11 September 2005 03:38, Colin Carter wrote:
On Sunday 11 September 2005 03:39, Anders Johansson wrote:
On Saturday 10 September 2005 17:47, Jerry Feldman wrote:
Just to add to Anders comments. According to the ANSI 89 standard, this is an unspecified operation. The issue here is when the postincrement operator is applied to s. C pushes variables from the last to the first because it may have an unknown number of parameters.
This is a completely unwarranted assumption. This may be the way any one compiler works (and it does make sense), but according to 6.5.2.2 of the 1999 standard
"The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call"
So while I'm sure you're right about any one compiler, it is very wrong to say that C does it, and suicidal to rely on it
I agree; you need to look at your own compilerS.
That's not what I said (or at least not what I meant :)
You need to look at your own code, and make sure you only code according to standards.
(Values? C passes values sometimes and addresses if it feels like it, so be careful.)
Parameters in C are always passed by value. If you want to have call by reference, you need to do that explicitly, by passing a pointer (in which case it's still call by value, since you're passing the value of the pointer)
The exception is when you have an array or function as parameter, in which case the pointer to it is passed, but this is well defined, not willy nilly
How about structures, character strings? See: a sometimes thing.
The relevant sections are 6.5.2.2 and 6.7.5.3 in the 1999 standard
So: Why in hell would anybody want to pass something as dumb as s++ ?
Well, it's not s++ that's passed, it's s. Having 's++' in the parameter list is just telling the compiler that s is to be incremented by one immediately after its value has been used in the function call. This can be useful as a hint to the compiler, so it can increment s while it's still held in a register. If you have s=s+1; on the next line, a clever compiler might still be able to detect it and rearrange things, but with the postfix notation it's much easier. Especially in tight inner loops, small tricks like this can have noticeable payoffs
Sorry, but I don't agree. Writing 'clever' code is confusing to the reader. Whereas a good compiler (eg FORTRAN) will improve code significantly better than most coders. For example J = J + 1 has been compiled as inc J for many years now, and FORTRAN has, for around thirty years, compiled 'do loops' ( K = 1 to 100) as load registers (minus 1) and decrement the counter from 99 to -1 in registers. A good FORTRAN compiler looks ahead and starts computing code in advance of the time the previous values will be required. That is, it can see things "coming up", and many lines of code will be computed out of sequence. Fancy code just inhibits optimisation. But you might already know this. :-) Regards, Colin
On Sunday 11 September 2005 09:45, Colin Carter wrote:
Parameters in C are always passed by value. If you want to have call by reference, you need to do that explicitly, by passing a pointer (in which case it's still call by value, since you're passing the value of the pointer)
The exception is when you have an array or function as parameter, in which case the pointer to it is passed, but this is well defined, not willy nilly
How about structures, character strings? See: a sometimes thing.
A character string isn't a separate type, it is an array, so that is covered by the above exception. Structures are passed by value Try running the following example program #include <stdio.h> struct a{ int a; long b; unsigned c; }; void func(struct a var){ printf("The address of var is %p\n", &var); } int main(void){ struct a var2; printf("The address of var2 is %p\n",&var2); func(var2); return 0; }
Sorry, but I don't agree. Writing 'clever' code is confusing to the reader. Whereas a good compiler (eg FORTRAN) will improve code significantly better than most coders. For example J = J + 1 has been compiled as inc J for many years now, and FORTRAN has, for around thirty years, compiled 'do loops' ( K = 1 to 100) as load registers (minus 1) and decrement the counter from 99 to -1 in registers. A good FORTRAN compiler looks ahead and starts computing code in advance of the time the previous values will be required. That is, it can see things "coming up", and many lines of code will be computed out of sequence.
Fancy code just inhibits optimisation.
Well, I didn't mean to imply that there was a real difference between x++ and x=x+1, I'm sure there isn't a compiler out there that won't translate both to the same machine instruction. But the question is when they do it. If you have a construct like foo(x); x++; Then before the second line there is a whole function call to consider, and the compiler may or may not be aware of the increment, so it is entirely conceivable that it generates code that calls the function, and on return reloads x from memory to increment it. If on the other hand you had made it foo(x++); then it is much easier for the compiler to generate the "good" code that increments x while it's still held in memory, saving one or two instructions along the way. Now, I'm not saying there aren't compilers that see the two as equivalent, I'm sure many, perhaps even most do. But you can't be sure, and that is one reason I use constructs like that. Another is that it's more compact and, to my eyes, elegant to use the *fix notation. I don't think it's *that* much more difficult to read
On Sunday 11 September 2005 13:27, Anders Johansson wrote:
then it is much easier for the compiler to generate the "good" code that increments x while it's still held in memory
argh. Still held in a register, I meant Very very true. On a register rich system (such as Alpha, IA64, PA-RISC) automatic variables may never be stored in memory. int increment2(int x) { int y = x + 2; return y; } In this case, x would be passed via register, y would be held in a scratch register, and the return value would also be placed in a register. Most likely, the compiler may not even store anything in
On Sun, 11 Sep 2005 13:32:05 +0200 Anders Johansson <andjoh@rydsbo.net> wrote: the prologue. (The prologue is where some function housekeeping is done. Contents of reserved registers are stored, return address is stored for addressability, ...) -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
Hi Anders, I will basically agree with you; I don't think that we disagree really, just being a little pedantic about trivia. And it is now 1 am here, so I must hit the sack. Good night. Regards, Colin PS: Out of interest, and respect for you, I will have a look at your code. On Sunday 11 September 2005 21:27, Anders Johansson wrote:
On Sunday 11 September 2005 09:45, Colin Carter wrote:
Parameters in C are always passed by value. If you want to have call by reference, you need to do that explicitly, by passing a pointer (in which case it's still call by value, since you're passing the value of the pointer)
The exception is when you have an array or function as parameter, in which case the pointer to it is passed, but this is well defined, not willy nilly
How about structures, character strings? See: a sometimes thing.
A character string isn't a separate type, it is an array, so that is covered by the above exception.
Structures are passed by value
Try running the following example program
#include <stdio.h>
struct a{ int a; long b; unsigned c; };
void func(struct a var){ printf("The address of var is %p\n", &var); }
int main(void){ struct a var2;
printf("The address of var2 is %p\n",&var2); func(var2);
return 0; }
Sorry, but I don't agree. Writing 'clever' code is confusing to the reader. Whereas a good compiler (eg FORTRAN) will improve code significantly better than most coders. For example J = J + 1 has been compiled as inc J for many years now, and FORTRAN has, for around thirty years, compiled 'do loops' ( K = 1 to 100) as load registers (minus 1) and decrement the counter from 99 to -1 in registers. A good FORTRAN compiler looks ahead and starts computing code in advance of the time the previous values will be required. That is, it can see things "coming up", and many lines of code will be computed out of sequence.
Fancy code just inhibits optimisation.
Well, I didn't mean to imply that there was a real difference between x++ and x=x+1, I'm sure there isn't a compiler out there that won't translate both to the same machine instruction. But the question is when they do it.
If you have a construct like
foo(x); x++;
Then before the second line there is a whole function call to consider, and the compiler may or may not be aware of the increment, so it is entirely conceivable that it generates code that calls the function, and on return reloads x from memory to increment it. If on the other hand you had made it
foo(x++);
then it is much easier for the compiler to generate the "good" code that increments x while it's still held in memory, saving one or two instructions along the way. Now, I'm not saying there aren't compilers that see the two as equivalent, I'm sure many, perhaps even most do. But you can't be sure, and that is one reason I use constructs like that. Another is that it's more compact and, to my eyes, elegant to use the *fix notation. I don't think it's *that* much more difficult to read
Fancy code just inhibits optimisation. Very, very true. In the olden days before C compilers had good optimizers, using
On Sun, 11 Sep 2005 17:45:16 +1000 Colin Carter <colincarter@exemail.com.au> wrote: pointers was more efficient than subscripts, but the use of a pointer requires the compiler to dereference the pointers on their use. Using subscripts allows the C compiler to better optimize the code. I mentioned that the Intel ICC compiler uses some very aggressive optimizations on the IA64. Additionally, fancy code makes a program less readable and hence less maintainable. One example from my ancient COBOL past on a Burroughs mainframe: ... Procedure division. start. enter symbolic ---> much assembler ----------------- This was not very portable code. -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
Colin Carter <colincarter@exemail.com.au> [11 Sep 2005 17:45:16 +1000]:
Whereas a good compiler (eg FORTRAN) will improve code significantly better than most coders.
Any modern compiler, no matter if it's FORTRAN,C,C++,Pascal or any other language, will optimize far better than most coders.
Fancy code just inhibits optimisation.
No, there are places where fancy code is necessary. Philipp
On Thursday 15 September 2005 10:10 pm, Philipp Thomas wrote:
Colin Carter <colincarter@exemail.com.au> [11 Sep 2005 17:45:16 +1000]:
Whereas a good compiler (eg FORTRAN) will improve code significantly better than most coders.
Any modern compiler, no matter if it's FORTRAN,C,C++,Pascal or any other language, will optimize far better than most coders.
Fancy code just inhibits optimisation.
No, there are places where fancy code is necessary. Philipp, I fully agree that there are places where fancy code may be necessary, but in many cases, fancy code does inhibit optimization, especially in C.
-- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
On Friday 16 September 2005 13:53, Jerry Feldman wrote:
I fully agree that there are places where fancy code may be necessary, but in many cases, fancy code does inhibit optimization, especially in C.
I think we need some sort of sane definition of the word "fancy" though. The obfuscated C code competition I would definitely agree with, I'm surprised most of that stuff compiles at all :) But I wouldn't include x++ in that definition
On Friday 16 September 2005 2:04 pm, Anders Johansson wrote:
On Friday 16 September 2005 13:53, Jerry Feldman wrote:
I fully agree that there are places where fancy code may be necessary, but in many cases, fancy code does inhibit optimization, especially in C.
I think we need some sort of sane definition of the word "fancy" though. The obfuscated C code competition I would definitely agree with, I'm surprised most of that stuff compiles at all :)
But I wouldn't include x++ in that definition In my case, I think that fancy would be any code that is not standard compliant and non-portable.
For instance the following code fragment is standards compliant but non-portable: long n; int i = -2; unsigned k = 1; n = i + k; I'll let you guys ponder this one for a while. -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
On Friday 16 September 2005 20:19, Jerry Feldman wrote:
For instance the following code fragment is standards compliant but non-portable: long n; int i = -2; unsigned k = 1; n = i + k;
sign extensions in promotions is something they really should have standardised by now. They haven't even standardised on the binary representation of negative numbers, so yes, it's another thing that's suicidal to rely on
On Saturday 17 September 2005 09:00, Anders Johansson wrote:
On Friday 16 September 2005 20:19, Jerry Feldman wrote:
For instance the following code fragment is standards compliant but non-portable: long n; int i = -2; unsigned k = 1; n = i + k;
sign extensions in promotions is something they really should have standardised by now. They haven't even standardised on the binary representation of negative numbers, [...]
Should a high level language be dictating to CPU manufacturers how processors must internally represents values?
On Saturday 17 September 2005 16:33, Synthetic Cartoonz wrote:
On Saturday 17 September 2005 09:00, Anders Johansson wrote:
On Friday 16 September 2005 20:19, Jerry Feldman wrote:
For instance the following code fragment is standards compliant but non-portable: long n; int i = -2; unsigned k = 1; n = i + k;
sign extensions in promotions is something they really should have standardised by now. They haven't even standardised on the binary representation of negative numbers, [...]
Should a high level language be dictating to CPU manufacturers how processors must internally represents values?
1. It already dictates that it must be binary 2. There is really no dictate about the representation. All the standards say it must behave *as if* this is how it's done. A good example is the standard include files, like stdio.h. The standard doesn't dictate that they must be present as regular files, it just dictates that if you have #include <stdio.h> in your program, a certain set of definitions will be assumed to be present, but this can be entirely internal to the compiler if this is deemed to be optimal. Another example is the preprocessor. So just as it is possible to have a strictly conforming implementation on a tertiary machine (where the compiler translates between the binary representation guaranteed by C to the tertiary representation of the hardware), it would be possible to say a negative number should be stored in two's complement with sign extension behaving in a certain way. Just let the compiler hide the gory details
On Sat, 17 Sep 2005 10:33:01 -0400 Synthetic Cartoonz <synthetoonz@bellsouth.net> wrote:
On Saturday 17 September 2005 09:00, Anders Johansson wrote:
On Friday 16 September 2005 20:19, Jerry Feldman wrote:
For instance the following code fragment is standards compliant but non-portable: long n; int i = -2; unsigned k = 1; n = i + k;
sign extensions in promotions is something they really should have standardised by now. They haven't even standardised on the binary representation of negative numbers, [...]
Should a high level language be dictating to CPU manufacturers how processors must internally represents values? Promotions and sign extensions are highly standardized by both the C89 and C99 standards. In this case, promotions work exactly as specified by c99. (I've verified this because I used this in a paper).
Languages dictate BEHAVIOR, not CPU or OS work. In this case, you will get a different result on 32-bits and 64-bits. -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
On Fri, 16 Sep 2005 20:04:29 +0200 Anders Johansson <andjoh@rydsbo.net> wrote:
But I wouldn't include x++ in that definition The pre-increment/post-increment (and decrement) operators are not fancy code in C, they are an integral part of the language, but they are often misused.
I also do not consider this fancy code: int c; while( (c = getchar()) != EOF) { ... } Note that I generally try to compare vs. NULL or 0, for example: 'if (p == NULL)' rather than 'if (!p)' Both are correct in C, but the second is less readable. -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
On Saturday 17 September 2005 14:48, Jerry Feldman wrote:
On Fri, 16 Sep 2005 20:04:29 +0200
Anders Johansson <andjoh@rydsbo.net> wrote:
But I wouldn't include x++ in that definition
The pre-increment/post-increment (and decrement) operators are not fancy code in C, they are an integral part of the language, but they are often misused.
I also do not consider this fancy code: int c; while( (c = getchar()) != EOF) {
I agree, that's standard practice
... }
Note that I generally try to compare vs. NULL or 0, for example: 'if (p == NULL)'
So you're not one of those who put potential lvalues to the right of the equality test, to make sure that a missed = makes it a syntax error rather than an unwanted assignment?
On Saturday 17 September 2005 08:48, Jerry Feldman wrote:
On Fri, 16 Sep 2005 20:04:29 +0200
Anders Johansson <andjoh@rydsbo.net> wrote:
But I wouldn't include x++ in that definition
The pre-increment/post-increment (and decrement) operators are not fancy code in C, they are an integral part of the language, but they are often misused.
I also do not consider this fancy code: int c; while( (c = getchar()) != EOF) { ... }
Note that I generally try to compare vs. NULL or 0, for example: 'if (p == NULL)'
Ouch. I've had to fix the typo'd version for this too many times: if ( p = NULL ) Syntactically permitted, but definitely not what is intended. If you have warnings turned off this is an invisible error until you run your program and it crashes. If you must do extra typing try this instead: if ( NULL == p ) The typo for this is an invalid assignment and will result in an error, not a warning at compile time.
rather than 'if (!p)' Both are correct in C, but the second is less readable.
I find this second version perfectly understandable, but I've been doing C for about 20 years.
I agree; you need to look at your own compilerS. I add the S because linking object code from two different languages can get one into a lot of trouble if they don't obey the same rules. Also one should note that some compilers pass addresses (best in my opinion) while others pass "values". (Values? C passes values sometimes and addresses if it feels like it, so be careful.) And some compilers pass 'hidden' information. This is true, but many systems have calling standards that define how functions and procedures are called. It is very important that the
On Sun, 11 Sep 2005 11:38:20 +1000 Colin Carter <colincarter@exemail.com.au> wrote: libraries all comply with a standard. For example, I use the Intel compiler on IA64 because it generates significantly faster code, but the system libraries are all generated by gcc, and some of the 3rd party binaries might be built with gcc or icc. Interoperability is what you are talking about. For instance, C and C++ pass parameters by value (C++ may also pass by reference). Languages like FORTRAN and COBOL pass parameters by reference. The compilation system must provide the interoperability tools. (Passing by reference in C is simply passing the address, so the C programmer needs to know what is being called). -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
On Saturday 10 September 2005 17:47, Jerry Feldman wrote:
Just to add to Anders comments. According to the ANSI 89 standard, this is an unspecified operation. The issue here is when the postincrement operator is applied to s. C pushes variables from the last to the first because it may have an unknown number of parameters.
This is a completely unwarranted assumption. This may be the way any one compiler works (and it does make sense), but according to 6.5.2.2 of the 1999 standard
"The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call"
So while I'm sure you're right about any one compiler, it is very wrong to say that C does it, and suicidal to rely on it This may have came across wrong. What I was describing the behavior exhibited by gcc on x86-32. GCC is certainly free to make any changes it wants as long as it is complient. (My copy of ISO 99 was at work). One should also note that I used the term "C pushes". On the x86 series, parameters are pushed on the stack. On other processors, such as Alpha, PA-RISC, IA64, some parameters are placed into registers and not pushed. This would cause the compiler to apply the
On Sat, 10 Sep 2005 19:39:53 +0200 Anders Johansson <andjoh@rydsbo.net> wrote: postincrement and postdecrement in a different order. There is a specific order in which the variables are pushed (or placed into registers), but the order in which their values are evaluated is unspecified. -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix user group http://www.blu.org PGP key id:C5061EA9 PGP Key fingerprint:053C 73EC 3AC1 5C44 3E14 9245 FB00 3ED5 C506 1EA9
participants (7)
-
Anders Johansson
-
Colin Carter
-
Jerry Feldman
-
Philipp Thomas
-
Randall R Schulz
-
Synthetic Cartoonz
-
Verdi March