445,797 Members | 1,848 Online
Need help? Post your question and get tips & solutions from a community of 445,797 IT Pros & Developers. It's quick & easy.

# coin toss problem

 P: n/a I've written this coin toss program, and can't figure out why it isn't giving accurate results... cheers, Ben #include #include #define H 1 #define T 0 #define SENTINEL -1 int count=0, seed=3645, limit=200, in_a_row=6, iterations=100; void one_run(int seed_passed) { int i, x, row_h; row_h = 0; seed=(1+seed_passed); srand(seed); char A[limit+1]; for(i=0;i
52 Replies

 P: n/a ce**********@hotmail.com wrote: I've written this coin toss program, and can't figure out why it isn't giving accurate results... cheers, Ben #include #include #define H 1 #define T 0 #define SENTINEL -1 int count=0, seed=3645, limit=200, in_a_row=6, iterations=100; void one_run(int seed_passed) { int i, x, row_h; row_h = 0; seed=(1+seed_passed); srand(seed); char A[limit+1]; This code should not compile unless you have a C99 system, which I doubt. limit+1 is not a constant, so the compiler has no idea what to do. In addition, you are defining storage after executable code. Turn up your warning levels. Also you are allowed to use blanks in expressions, the blank embargo was lifted some years ago. -- "A man who is right every time is not likely to do very much." -- Francis Crick, co-discover of DNA "There is nothing more amazing than stupidity in action." -- Thomas Matthews Jun 17 '06 #2

 P: n/a CBFalconer wrote: ce**********@hotmail.com wrote:I've written this coin toss program, and can't figure out why it isn'tgiving accurate results...cheers,Ben#include #include #define H 1#define T 0#define SENTINEL -1int count=0, seed=3645, limit=200, in_a_row=6, iterations=100;void one_run(int seed_passed){ int i, x, row_h; row_h = 0; seed=(1+seed_passed); srand(seed); char A[limit+1]; This code should not compile unless you have a C99 system, which I doubt. Why? Compiles fine with either compiler on mine. -- Ian Collins. Jun 17 '06 #3

 P: n/a wrote: I've written this coin toss program, and can't figure out why it isn't giving accurate results... I don't know what your problem is but I will make some observations anyway. First of all, get rid of the global variables. There is no need to resort to global variables in a program this small and simple. Is there any reason not to use enum instead of the #defines? They are more appropriate and would probably do what you want. Don't use the sentinel. Sentinels are something you resort to when there is a good reason. There is no good reason here. Reduce the program to its essence. You seem to be able to handle command line, a default set of data, or user supplied data. This is just obfuscating things right now. Choose one. I would use built in data for initial testing. Pay attention to the definition of in_a_row. Does it mean *exactly* n in a row? The code says no. To determine that your code would have to look at the next character - the one that breaks the sequence- , and it doesn't do that. To me, exactly is the most sensible thing to compute. For example, if in_a_row is 3 what does the following sequence of heads get counted as: 001111111100 ? I tried the corner cases, in a row = 1 and in a row = 0 and got strange results. You might refuse to accept such questions as n = 1 in the final version of your code. The crucial number is count. If you still have problems, add code to print the raw value of count. There are also a few embedded comments. #include #include #define H 1 #define T 0 #define SENTINEL -1 int count=0, seed=3645, limit=200, in_a_row=6, iterations=100; void one_run(int seed_passed) { int i, x, row_h; row_h = 0; Don't separate the definition from the initial value. IOW int row_h = 0; seed=(1+seed_passed); srand(seed); char A[limit+1]; for(i=0;i

 P: n/a Ian Collins said: CBFalconer wrote: ce**********@hotmail.com wrote: int count=0, seed=3645, limit=200, in_a_row=6, iterations=100; char A[limit+1]; This code should not compile unless you have a C99 system, which I doubt. Why? Compiles fine with either compiler on mine. If you're using a C99 compiler, well, fair enough. If you're using a compiler adhering to an older standard, like 99.90813774% of us, then your C compiler is required to issue a diagnostic message for the above code, which violates this constraint: "The expression that specifies the size of an array shall be an integral constant expression that has a value greater than zero." Since limit+1 is not an integral constant expression, a diagnostic message is required. -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at above domain (but drop the www, obviously) Jun 17 '06 #5

 P: n/a osmium wrote: int i, x, row_h; row_h = 0; Don't separate the definition from the initial value. IOW int row_h = 0; Is there a reason to use an initialization instead of an assignment after the declaration? I prefer declaring and then assigning, but the only reason is that I find it annoying when I'm debugging and the debugger stops in the declaration block. Is this more than just a stylistic issue, or do some compilers generate different code for the 2 cases? Jun 17 '06 #6

 P: n/a "Bill Pursell" writes: osmium wrote: > int i, x, row_h; > row_h = 0; Don't separate the definition from the initial value. IOW int row_h = 0; Is there a reason to use an initialization instead of an assignment after the declaration? I prefer declaring and then assigning, but the only reason is that I find it annoying when I'm debugging and the debugger stops in the declaration block. Is this more than just a stylistic issue, or do some compilers generate different code for the 2 cases? My objection was based on documentation. I found a place in his code where the value seemed to be an un-initialized datum. In fact it wasn't, but the initialization was hidden, at least from me. For a while. I doubt if there are any non-stylistic issues. Jun 17 '06 #7

 P: n/a wrote in message news:11**********************@r2g2000cwb.googlegro ups.com... cheers, Ben #include #include #define H 1 #define T 0 #define SENTINEL -1 I might be able to provide comment on your data, but I crap out right here. Unlike Keith Thompson, I am not 100% certain what this ultimate statement means. BTW, I'm not even sure that 'statement" is the right descriptor for something that doesn't necessarily end in a ';'. Anyways, #define SENTINEL -1 probably instructs the preprocessor to replace every instance of SENTINEL with negative one. When I looked at it, I thought you were decrementing. I think better form would be #define SENTINEL '-1' or #define SENTINEL (-1) , I'm not sure which, but since '-' is a token, it needs something. Post your "howdy and thanks, ben" below, so that they can be easily snipped. furunculus Jun 17 '06 #8

 P: n/a Bill Pursell wrote: osmium wrote: int i, x, row_h; row_h = 0; Don't separate the definition from the initial value. IOW int row_h = 0; Is there a reason to use an initialization instead of an assignment after the declaration? I prefer declaring and then assigning, So do I. but the only reason is that I find it annoying when I'm debugging and the debugger stops in the declaration block. I prefer to initialise just prior to usage because my compiler issues a warning for unused variables, which is a warning that I like. My compiler considers an initialised variable, to be a used one. -- pete Jun 17 '06 #9

 P: n/a Joe Smith wrote: wrote in message news:11**********************@r2g2000cwb.googlegro ups.com... #define SENTINEL -1 I think better form would be #define SENTINEL '-1' or #define SENTINEL (-1) , I'm not sure which, but since '-' is a token, it needs something. I prefer #define SENTINEL (-1) because I don't know what '-1' means. -- pete Jun 17 '06 #10

 P: n/a osmium wrote: "Bill Pursell" writes: .... snip ... Is there a reason to use an initialization instead of an assignment after the declaration? I prefer declaring and then assigning, but the only reason is that I find it annoying when I'm debugging and the debugger stops in the declaration block. Is this more than just a stylistic issue, or do some compilers generate different code for the 2 cases? My objection was based on documentation. I found a place in his code where the value seemed to be an un-initialized datum. In fact it wasn't, but the initialization was hidden, at least from me. For a while. I doubt if there are any non-stylistic issues. IMO the opposite is true. Since initialization of automatic variables always involves generating code, lets have that code where it is obviously such. If the routine is so long and involved that you can miss the actual initialization, then it should be chopped up into smaller more understandable portions. That way you also avoid generating useless code for initializations that are always just overwritten. One further benefit: if you port your code to some C-like embedded system with an almost C compiler, it has a better chance of surviving unscathed. -- "A man who is right every time is not likely to do very much." -- Francis Crick, co-discover of DNA "There is nothing more amazing than stupidity in action." -- Thomas Matthews Jun 17 '06 #11

 P: n/a Richard Heathfield wrote: Ian Collins said:CBFalconer wrote:ce**********@hotmail.com wrote: int count=0, seed=3645, limit=200, in_a_row=6, iterations=100; char A[limit+1]; This code should not compile unless you have a C99 system, which Idoubt.Why? Compiles fine with either compiler on mine. If you're using a C99 compiler, well, fair enough. If you're using a compiler adhering to an older standard, like 99.90813774% of us, then your C compiler is required to issue a diagnostic message for the above code, which violates this constraint: "The expression that specifies the size of an array shall be an integral constant expression that has a value greater than zero." Since limit+1 is not an integral constant expression, a diagnostic message is required. Are Solaris users realy that small a minority? Also gcc has supported variable length arrays as an extension for many years. I've suffered the pain of porting from gcc more than once. -- Ian Collins. Jun 17 '06 #12

 P: n/a Richard Heathfield writes: Ian Collins said: CBFalconer wrote: ce**********@hotmail.com wrote: int count=0, seed=3645, limit=200, in_a_row=6, iterations=100; char A[limit+1]; This code should not compile unless you have a C99 system, which I doubt. Why? Compiles fine with either compiler on mine. If you're using a C99 compiler, well, fair enough. If you're using a compiler adhering to an older standard, like 99.90813774% of us, then your C compiler is required to issue a diagnostic message for the above code, which violates this constraint: "The expression that specifies the size of an array shall be an integral constant expression that has a value greater than zero." Since limit+1 is not an integral constant expression, a diagnostic message is required. It also has declarations following statements within a block. Both of these features are supported by C99 but not by C90. (They're also supported by C++, and possibly by some C90 compilers in a non-conforming mode.) -- Keith Thompson (The_Other_Keith) ks***@mib.org San Diego Supercomputer Center <*> We must do something. This is something. Therefore, we must do this. Jun 17 '06 #13

 P: n/a pete wrote: Joe Smith wrote: wrote in messagenews:11**********************@r2g2000cwb.googleg roups.com...#define SENTINEL -1I think better form would be#define SENTINEL '-1'or#define SENTINEL (-1), I'm not sure which, but since '-' is a token, it needs something. I prefer #define SENTINEL (-1) because I don't know what '-1' means. Why not just use const int? -- Ian Collins. Jun 17 '06 #14

 P: n/a pete writes: Joe Smith wrote: wrote in message news:11**********************@r2g2000cwb.googlegro ups.com... > #define SENTINEL -1 I think better form would be #define SENTINEL '-1' or #define SENTINEL (-1) , I'm not sure which, but since '-' is a token, it needs something. I prefer #define SENTINEL (-1) because I don't know what '-1' means. I know what '-1' means. It means an implementation-defined value of type int. It's unlikely to be what you want here. (Actually it will probably work as long as the value is neither 0 nor 1, but it's a silly way to do it.) If you want to define a macro with the value -1, you should definitely add parentheses: #define SENTINEL (-1) to avoid operator precedence problems. Joe, your suggestion of #define SENTINEL '-1' was obviously a wild guess. That's fine if you're asking a question, but I suggest that it's counterproductive if you're trying to answer a question. -- Keith Thompson (The_Other_Keith) ks***@mib.org San Diego Supercomputer Center <*> We must do something. This is something. Therefore, we must do this. Jun 17 '06 #15

 P: n/a Keith Thompson wrote: Richard Heathfield writes:Ian Collins said:CBFalconer wrote:ce**********@hotmail.com wrote:>int count=0, seed=3645, limit=200, in_a_row=6, iterations=100;>> char A[limit+1]; This code should not compile unless you have a C99 system, which Idoubt.Why? Compiles fine with either compiler on mine.If you're using a C99 compiler, well, fair enough. If you're using acompiler adhering to an older standard, like 99.90813774% of us, then yourC compiler is required to issue a diagnostic message for the above code,which violates this constraint: "The expression that specifies the size ofan array shall be an integral constant expression that has a value greaterthan zero." Since limit+1 is not an integral constant expression, adiagnostic message is required. It also has declarations following statements within a block. Both of these features are supported by C99 but not by C90. (They're also supported by C++, and possibly by some C90 compilers in a non-conforming mode.) No, VLAs are not supported by C++ (yet). A constant expression is required. g++ has them as an (irritating for porters) extension. -- Ian Collins. Jun 17 '06 #16

 P: n/a Ian Collins said: Richard Heathfield wrote: Ian Collins said:CBFalconer wrote:ce**********@hotmail.com wrote: >int count=0, seed=3645, limit=200, in_a_row=6, iterations=100;> > char A[limit+1]; This code should not compile unless you have a C99 system, which Idoubt.Why? Compiles fine with either compiler on mine. If you're using a C99 compiler, well, fair enough. If you're using a compiler adhering to an older standard, like 99.90813774% of us, then your C compiler is required to issue a diagnostic message for the above code, which violates this constraint: "The expression that specifies the size of an array shall be an integral constant expression that has a value greater than zero." Since limit+1 is not an integral constant expression, a diagnostic message is required. Are Solaris users realy that small a minority? The 99.90813774% figure makes up in precision what it lacks in accuracy. :-) But seriously, if Solaris is relevant to your point then your point is almost certainly irrelevant to comp.lang.c. Yes, the code is valid C99, as I already pointed out in my earlier reply, so if you are using a C99 compiler then the code is legal. But it is not /portable/ - for example, it won't compile on the implementation I am presently using. Also gcc has supported variable length arrays as an extension for many years. Using extensions is fine until the time comes to port. At that point, the pain hits. If you want to avoid the pain, either avoid the port or avoid the extensions. I've suffered the pain of porting from gcc more than once. See? -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at above domain (but drop the www, obviously) Jun 17 '06 #17

 P: n/a Richard Heathfield wrote: Ian Collins said:Richard Heathfield wrote:If you're using a C99 compiler, well, fair enough. If you're using acompiler adhering to an older standard, like 99.90813774% of us, thenyour C compiler is required to issue a diagnostic message for the abovecode, which violates this constraint: "The expression that specifies thesize of an array shall be an integral constant expression that has avalue greater than zero." Since limit+1 is not an integral constantexpression, a diagnostic message is required.Are Solaris users realy that small a minority? The 99.90813774% figure makes up in precision what it lacks in accuracy. :-) But seriously, if Solaris is relevant to your point then your point is almost certainly irrelevant to comp.lang.c. Yes, the code is valid C99, as I already pointed out in my earlier reply, so if you are using a C99 compiler then the code is legal. But it is not /portable/ - for example, it won't compile on the implementation I am presently using. My poorly made point was that C99 is more widely available than some people make out. I still find the "it's new so I won't use it" argument hard to swallow. Every new tool or technology has its early adopters (if 6 years on is early!). If no one uses new stuff because it isn't portable, progress would grind to a halt. -- Ian Collins. Jun 17 '06 #18

 P: n/a Ian Collins said: My poorly made point was that C99 is more widely available than some people make out. True. It is also /less/ widely available than some people make out. I still find the "it's new so I won't use it" argument hard to swallow. Nobody is arguing that as far as I can see. The reason I don't use C99 features is that they're not portable, so using those features makes my code non-portable. When C99 becomes widespread, that'll be great, marvellous, and fantastic, and suddenly I'll be able to use VLAs if I want (not that I see the point) - but in the meantime I'm not holding my breath. -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at above domain (but drop the www, obviously) Jun 17 '06 #19

 P: n/a Keith Thompson wrote: pete writes:Joe Smith wrote: wrote in messagenews:11**********************@r2g2000cwb.google groups.com...#define SENTINEL -1I think better form would be#define SENTINEL '-1'or#define SENTINEL (-1), I'm not sure which, but since '-' is a token, it needs something. I prefer#define SENTINEL (-1) because I don't know what '-1' means. I know what '-1' means. It means an implementation-defined value of type int. It's unlikely to be what you want here. (Actually it will probably work as long as the value is neither 0 nor 1, but it's a silly way to do it.) If you want to define a macro with the value -1, you should definitely add parentheses: #define SENTINEL (-1) to avoid operator precedence problems. For example, int array[] = { 1, 2, 3 }, *p = array + 1; printf ("%d\n", SENTINEL[p]); .... outputs "-3\n" if SENTINEL is -1, but "1\n" if it is (-1). (I *think* the only way to form an expression where the presence or absence of parentheses around -1 makes a difference is to use the bass-ackward array notation as above. Can anyone come up with another?) -- Eric Sosman es*****@acm-dot-org.invalid Jun 17 '06 #20

 P: n/a Ian Collins writes: Keith Thompson wrote: [...] It also has declarations following statements within a block. Both of these features are supported by C99 but not by C90. (They're also supported by C++, and possibly by some C90 compilers in a non-conforming mode.) No, VLAs are not supported by C++ (yet). A constant expression is required. g++ has them as an (irritating for porters) extension. See, that's what I get for discussing C++ in comp.lang.c! (I was probably thinking of the fact that C++ has a looser definition of constant expressions than C has; some things that would be VLAs in C are ordinary constant-size arrays in C++.) -- Keith Thompson (The_Other_Keith) ks***@mib.org San Diego Supercomputer Center <*> We must do something. This is something. Therefore, we must do this. Jun 17 '06 #21

 P: n/a Ian Collins writes: Richard Heathfield wrote: [...] If you're using a C99 compiler, well, fair enough. If you're using a compiler adhering to an older standard, like 99.90813774% of us, then your C compiler is required to issue a diagnostic message for the above code, which violates this constraint: "The expression that specifies the size of an array shall be an integral constant expression that has a value greater than zero." Since limit+1 is not an integral constant expression, a diagnostic message is required. Are Solaris users realy that small a minority? Are you saying that Sun's compiler fully supports C99? If so, it's news to me. What version? -- Keith Thompson (The_Other_Keith) ks***@mib.org San Diego Supercomputer Center <*> We must do something. This is something. Therefore, we must do this. Jun 17 '06 #22

 P: n/a Richard Heathfield wrote: Ian Collins said:My poorly made point was that C99 is more widely available than somepeople make out. True. It is also /less/ widely available than some people make out.I still find the "it's new so I won't use it" argument hard to swallow. Nobody is arguing that as far as I can see. The reason I don't use C99 features is that they're not portable, so using those features makes my code non-portable. When C99 becomes widespread, that'll be great, marvellous, and fantastic, and suddenly I'll be able to use VLAs if I want (not that I see the point) - but in the meantime I'm not holding my breath. It's a classic chicken and egg situation, users won't use it because it isn't portable, vendors won't support it because users won't use it! -- Ian Collins. Jun 17 '06 #23

 P: n/a Keith Thompson wrote: Ian Collins writes:Richard Heathfield wrote: [...]If you're using a C99 compiler, well, fair enough. If you're using acompiler adhering to an older standard, like 99.90813774% of us, then yourC compiler is required to issue a diagnostic message for the above code,which violates this constraint: "The expression that specifies the size ofan array shall be an integral constant expression that has a value greaterthan zero." Since limit+1 is not an integral constant expression, adiagnostic message is required.Are Solaris users realy that small a minority? Are you saying that Sun's compiler fully supports C99? If so, it's news to me. What version? Studio 11 is getting close. As close as their C++ compiler was to the C++ standard a few years ago. -- Ian Collins. Jun 17 '06 #24

 P: n/a Keith Thompson wrote: Ian Collins writes:Keith Thompson wrote: [...]It also has declarations following statements within a block. Both ofthese features are supported by C99 but not by C90. (They're alsosupported by C++, and possibly by some C90 compilers in anon-conforming mode.)No, VLAs are not supported by C++ (yet). A constant expression isrequired. g++ has them as an (irritating for porters) extension. See, that's what I get for discussing C++ in comp.lang.c! (I was probably thinking of the fact that C++ has a looser definition of constant expressions than C has; some things that would be VLAs in C are ordinary constant-size arrays in C++.) Yes, that's correct. Another thing I find strange in C: why isn't 'const int' a constant expression? -- Ian Collins. Jun 17 '06 #25

 P: n/a Ian Collins writes: Keith Thompson wrote: Ian Collins writes:Keith Thompson wrote: [...]It also has declarations following statements within a block. Both ofthese features are supported by C99 but not by C90. (They're alsosupported by C++, and possibly by some C90 compilers in anon-conforming mode.) No, VLAs are not supported by C++ (yet). A constant expression isrequired. g++ has them as an (irritating for porters) extension. See, that's what I get for discussing C++ in comp.lang.c! (I was probably thinking of the fact that C++ has a looser definition of constant expressions than C has; some things that would be VLAs in C are ordinary constant-size arrays in C++.) Yes, that's correct. Another thing I find strange in C: why isn't 'const int' a constant expression? Because "const" doesn't really mean "constant" (at least not in the sense used in the phrase "constant expression"); it means "read-only". #include #include #include int main(void) { srand(time(NULL)); const int r = rand(); printf("r = %d\n", r); return 0; } Yes, the similarity between the word "constant" and the keyword "const" is an unforunate source of confusion. -- Keith Thompson (The_Other_Keith) ks***@mib.org San Diego Supercomputer Center <*> We must do something. This is something. Therefore, we must do this. Jun 17 '06 #26

 P: n/a On 2006-06-17, Ian Collins wrote: Keith Thompson wrote: Ian Collins writes:Keith Thompson wrote: [...]It also has declarations following statements within a block. Both ofthese features are supported by C99 but not by C90. (They're alsosupported by C++, and possibly by some C90 compilers in anon-conforming mode.) No, VLAs are not supported by C++ (yet). A constant expression isrequired. g++ has them as an (irritating for porters) extension. See, that's what I get for discussing C++ in comp.lang.c! (I was probably thinking of the fact that C++ has a looser definition of constant expressions than C has; some things that would be VLAs in C are ordinary constant-size arrays in C++.) Yes, that's correct. Another thing I find strange in C: why isn't 'const int' a constant expression? Well, there is a difference: A "constant expression" must be known at compile-time, a const int can be initialized with an expression that isn't evaluated until runtime, you just can't (or shouldn't) then change the value. I may be wrong (and hope to be corrected if I am), but I don't think "casting away const" causes any undefined behaviour. In C++ you've got some special rules that mean "const int a = 2;" can safely go in a header-file (i.e. you can include it in a lot of source files and not end up with "duplicate symbol" errors), and works pretty much just like "#define a (2)". But in "const int b = f();", "const int" has a meaning much closer to what it always means in C. I find this strange in C++. Jun 17 '06 #27

 P: n/a Ben C wrote: On 2006-06-17, Ian Collins wrote:Another thing I find strange in C: why isn't'const int' a constant expression? Well, there is a difference: A "constant expression" must be known at compile-time, a const int can be initialized with an expression that isn't evaluated until runtime, you just can't (or shouldn't) then change the value. I may be wrong (and hope to be corrected if I am), but I don't think "casting away const" causes any undefined behaviour. const int a = 2; *(int*)(&a) = 3; would cause UB. In C++ you've got some special rules that mean "const int a = 2;" can safely go in a header-file (i.e. you can include it in a lot of source files and not end up with "duplicate symbol" errors), and works pretty much just like "#define a (2)". But in "const int b = f();", "const int" has a meaning much closer to what it always means in C. I find this strange in C++. Touché! "const int a = 2;" is a compile time constant, where as "const int b = f();" isn't. I guess the clarity of the distinction depends on one's view of the world. -- Ian Collins. Jun 17 '06 #28

 P: n/a Ian Collins wrote: .... snip ... Also gcc has supported variable length arrays as an extension for many years. I've suffered the pain of porting from gcc more than once. gcc, without suitable parameters, is NOT a C compiler. The minimum recommended options for using it for portable coding are: gcc -W -Wall -ansi -pedantic which will convert it into a first class C90 compiler. You can replace -ansi with -std=C99 to have a fairly good C99 compiler. I add -O1 -Wwrite-strings -Wfloat-equal. Note that non-portable code is NOT discussed here. -- "A man who is right every time is not likely to do very much." -- Francis Crick, co-discover of DNA "There is nothing more amazing than stupidity in action." -- Thomas Matthews Jun 17 '06 #29

 P: n/a CBFalconer wrote: Ian Collins wrote: .... snip ...Also gcc has supported variable length arrays as an extension formany years. I've suffered the pain of porting from gcc more thanonce. gcc, without suitable parameters, is NOT a C compiler. The minimum recommended options for using it for portable coding are: gcc -W -Wall -ansi -pedantic which will convert it into a first class C90 compiler. You can replace -ansi with -std=C99 to have a fairly good C99 compiler. I add -O1 -Wwrite-strings -Wfloat-equal. Note that non-portable code is NOT discussed here. Yawn... But C99 is and the above mentioned gcc extension has been incorporated into the standard. -- Ian Collins. Jun 17 '06 #30

 P: n/a Richard Heathfield writes: [...] your C compiler is required to issue a diagnostic message for the above code, which violates this constraint: "The expression that specifies the size of an array shall be an integral constant expression that has a value greater than zero." Since limit+1 is not an integral constant expression, a diagnostic message is required. I am not sure it is required, because of the following dictum in the standard (in C99 it's 6.6p10; I seem to recall seeing the same sentence in C90): An implementation may accept other forms of constant expressions. -- int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\ \n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\ );while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\ );}return 0;} Jun 18 '06 #31

 P: n/a Ben Pfaff said: Richard Heathfield writes: [...] your C compiler is required to issue a diagnostic message for the above code, which violates this constraint: "The expression that specifies the size of an array shall be an integral constant expression that has a value greater than zero." Since limit+1 is not an integral constant expression, a diagnostic message is required. I am not sure it is required, because of the following dictum in the standard (in C99 it's 6.6p10; I seem to recall seeing the same sentence in C90): An implementation may accept other forms of constant expressions. I can't find that phrase in my C89 draft. A final trumps a draft, of course, but I think my draft is quite close to the final. Do you have an exact cite from C90? Just to be clear that I have no quibble about its being legal C99, because C99 does support VLAs. This is purely a C89/90/95/callitwhatyouwill issue. -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at above domain (but drop the www, obviously) Jun 18 '06 #32

 P: n/a Ian Collins said: CBFalconer wrote: Ian Collins wrote: .... snip ...Also gcc has supported variable length arrays as an extension formany years. I've suffered the pain of porting from gcc more thanonce. gcc, without suitable parameters, is NOT a C compiler. The minimum recommended options for using it for portable coding are: gcc -W -Wall -ansi -pedantic which will convert it into a first class C90 compiler. You can replace -ansi with -std=C99 to have a fairly good C99 compiler. I add -O1 -Wwrite-strings -Wfloat-equal. Note that non-portable code is NOT discussed here. Yawn... But C99 is and the above mentioned gcc extension has been incorporated into the standard. No, gcc's VLAs have not been incorporated into the Standard. The semantics of gcc VLAs differs from that of C99 VLAs, according to gcc's own documentation. -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at above domain (but drop the www, obviously) Jun 18 '06 #33

 P: n/a Richard Heathfield wrote: Ben Pfaff said: I am not sure it is required, because of the following dictum in the standard (in C99 it's 6.6p10; I seem to recall seeing the same sentence in C90): An implementation may accept other forms of constant expressions. I can't find that phrase in my C89 draft. A final trumps a draft, of course, but I think my draft is quite close to the final. Do you have an exact cite from C90? ISO/IEC 9899: 1990 6.4 Constant expressions Semantics An implementation may accept other forms of constant expressions. -- pete Jun 18 '06 #34

 P: n/a Richard Heathfield wrote: Ian Collins said:But C99 is and the above mentioned gcc extension has been incorporatedinto the standard. No, gcc's VLAs have not been incorporated into the Standard. The semantics of gcc VLAs differs from that of C99 VLAs, according to gcc's own documentation. My lesson for the day, I'd better go and look it up! Cheers, -- Ian Collins. Jun 18 '06 #35

 P: n/a pete said: Richard Heathfield wrote: Ben Pfaff said: > I am not sure it is required, because of the following dictum in > the standard (in C99 it's 6.6p10; I seem to recall seeing the > same sentence in C90): > > An implementation may accept other forms of constant > expressions. I can't find that phrase in my C89 draft. A final trumps a draft, of course, but I think my draft is quite close to the final. Do you have an exact cite from C90? ISO/IEC 9899: 1990 6.4 Constant expressions Semantics An implementation may accept other forms of constant expressions. Fair enough. The obvious implication is that a developer may get a clean compile on one implementation, and yet get a show-stopping constraint violation on another. So, if your goal is portable code, steer clear. -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at above domain (but drop the www, obviously) Jun 18 '06 #36

 P: n/a CBFalconer wrote: ce**********@hotmail.com wrote: I've written this coin toss program, and can't figure out why it isn't giving accurate results... cheers, Ben #include #include #define H 1 #define T 0 #define SENTINEL -1 int count=0, seed=3645, limit=200, in_a_row=6, iterations=100; void one_run(int seed_passed) { int i, x, row_h; row_h = 0; seed=(1+seed_passed); srand(seed); char A[limit+1]; This code should not compile unless you have a C99 system, which I doubt. limit+1 is not a constant, so the compiler has no idea what to do. In addition, you are defining storage after executable code. Turn up your warning levels. Also you are allowed to use blanks in expressions, the blank embargo was lifted some years ago. ....and you can take that to the blank. I laughed all the way... -- +----------------------------------------------------------------+ | Charles and Francis Richmond richmond at plano dot net | +----------------------------------------------------------------+ Jun 18 '06 #37

 P: n/a Hi, I don't know what your problem is but I will make some observations anyway. My initial problem was that I had read in a maths book that the average no. of 6 heads in a row in a sequence of 200 tosses was at least one... my program kept providing 0.77 I have since realised that they must have meant "at least 6"... First of all, get rid of the global variables. There is no need to resort to global variables in a program this small and simple. I only started learning programming a few months ago- so I'm not sure what the problem is with global variables? (And what's an alternative?) Is there any reason not to use enum instead of the #defines? They are more appropriate and would probably do what you want. The #defines seem to do what I want - enums might be more appropriate, but I haven't yet learnt what they are :) Don't use the sentinel. Sentinels are something you resort to when there is a good reason. There is no good reason here. The sentinel seemed easy enough to use - what potential problems are there with using them? Why are they only a last resort? Reduce the program to its essence. You seem to be able to handle command line, a default set of data, or user supplied data. This is just obfuscating things right now. Choose one. I would use built in data for initial testing. The command line data is just for the seed, so I can manually assess the degree of probability accuracy ... the default data is probably unnecessary. Pay attention to the definition of in_a_row. Does it mean *exactly* n in a row? The code says no. To determine that your code would have to look at the next character - the one that breaks the sequence- , and it doesn't do that. To me, exactly is the most sensible thing to compute. For example, if in_a_row is 3 what does the following sequence of heads get counted as: 001111111100 ? It does compute 'exactly x in a row' ... which is what I intended... (it looks at the character that breaks the sequence when 'i' is incremented - which breaks the while loop) while(A[i]==H) { i++; row_h++; } if(row_h==in_a_row) count++; row_h=0; I tried the corner cases, in a row = 1 and in a row = 0 and got strange results. You might refuse to accept such questions as n = 1 in the final version of your code. I'd like to be able to test for n=1 ... so I'll keep trying :) If n=0, I could just assign the number of tosses to n, and test for that instead. x=(int)(2.0*rand()/(1.0+RAND_MAX)); Too complicated. Note that if the number drawn is less than 1/2 RAND_MAX, you have divided the distribution into two almost equal parts. My uni textbook says "If you need your program to be portable, and require the values to be uncorelated even when compiled with the original rand and srand functions, you should extract the desired value from high-order bits rather than low-order ones..." (av_occur=1.0*count/iterations); What are those parens for? Just a kind of idle question. I'm a newbie ... by habbit I tend to stick in as many extra parens as possible ;) (I realise now they are reduntant). Jun 18 '06 #38

 P: n/a Andrew Poelstra writes: [...] enums are lists of variables: enum MyList { itemOne, itemTwo, itemThree }; results in itemOne being 0, itemTwo being 1, and itemThree being 2. You can also add in definitions: Quibble: constants, not variables. -- Keith Thompson (The_Other_Keith) ks***@mib.org San Diego Supercomputer Center <*> We must do something. This is something. Therefore, we must do this. Jun 18 '06 #40

 P: n/a "osmium" writes: "Ben" wrote: [...] The sentinel seemed easy enough to use - what potential problems are there with using them? Why are they only a last resort? Not many problems, they just make you look like a student. Instructors often teach the use of sentinels to avoid teaching how to handle end of file. The thought is that sentinels are easier to understand, and I agree. But real programmers use end of file. Using a sentinel when reading a file, rather than checking for EOF, is rarely a good idea. But sentinels can be useful in other contexts. Consider a function that takes a variable number of pointer arguments. Using a null pointer as a sentinel is a reasonable approach. -- Keith Thompson (The_Other_Keith) ks***@mib.org San Diego Supercomputer Center <*> We must do something. This is something. Therefore, we must do this. Jun 18 '06 #42

 P: n/a On 2006-06-17, Ian Collins wrote: Ben C wrote: On 2006-06-17, Ian Collins wrote:Another thing I find strange in C: why isn't'const int' a constant expression? Well, there is a difference: A "constant expression" must be known at compile-time, a const int can be initialized with an expression that isn't evaluated until runtime, you just can't (or shouldn't) then change the value. I may be wrong (and hope to be corrected if I am), but I don't think "casting away const" causes any undefined behaviour. const int a = 2; *(int*)(&a) = 3; would cause UB. Why? Is this something to do with "type-punning"-- we're taking the address of an object of one type (const int) and making a pointer to another type (int) point to it, then dereferencing. This is always UB. It allows for machines to use different sizes and shapes of pointers to different types if they want to. But const int a = 2; (int) a = 3; is not UB, right? In C++ you've got some special rules that mean "const int a = 2;" can safely go in a header-file (i.e. you can include it in a lot of source files and not end up with "duplicate symbol" errors), and works pretty much just like "#define a (2)". But in "const int b = f();", "const int" has a meaning much closer to what it always means in C. I find this strange in C++. Touché! "const int a = 2;" is a compile time constant, where as "const int b = f();" isn't. I guess the clarity of the distinction depends on one's view of the world. IIRC, in "The Design and Evolution of C++" Stroustrup justifies this as part of a general crusade against the C preprocessor (which he aptly describes as a "bulldozer"). In C# you get two different keywords-- "readonly" and "const" instead of using "const" to mean both. Jun 18 '06 #43

 P: n/a Richard Heathfield wrote: Ian Collins said: CBFalconer wrote: This code should not compile unless you have a C99 system, which I doubt. Why? Compiles fine with either compiler on mine. If you're using a C99 compiler, well, fair enough. If you're using a compiler adhering to an older standard, like 99.90813774% of us, GCC seems to be the most common compiler around. In its default mode it accepts many C99 constructs. So I think your figure should be revised downwards somewhat. Jun 18 '06 #44

 P: n/a Ben C wrote: But const int a = 2; (int) a = 3; is not UB, right? Well, it should fail to compile. (int)a is not an lvalue. Whether or not constraint violations are UB is a bit of an academic matter (half the NG seems to think they are and half think they aren't). Jun 18 '06 #45

 P: n/a "osmium" writes: Here's another cut at it. I see the copy I posted is where I was fooling around trying to see how many trials it took to get a result of 1.0 It is in the vicinity of 128 trials. Change the 128 to 200 to customize this to your question. Also note this was compiled on a compiler that accepts some C99 syntax, E.g., \\ comments. Note that if you had six coins and flipped them all, you would get six heads with probability .0156 . That's available from tables of the binomial distribution. A good statistics book will have that in the appendix. Jun 19 '06 #46

 P: n/a Eric Sosman wrote: For example, int array[] = { 1, 2, 3 }, *p = array + 1; printf ("%d\n", SENTINEL[p]); ... outputs "-3\n" if SENTINEL is -1, but "1\n" if it is (-1). (I *think* the only way to form an expression where the presence or absence of parentheses around -1 makes a difference is to use the bass-ackward array notation as above. Can anyone come up with another?) In pre-ANSI C we had: int a = 1; a =SENTINEL; forming the =- operator. Technically there is this: #define PP(X) #X #define PS(X) PP(X) size_t value = sizeof PS(SENTINEL); The only binary operators with higher precedence that unary minus are () [] -> . and I don't see how to apply any of them apart from []. We could have: void f(int i) { } meaning that f SENTINEL is an expression (albeit, an expression that violates a constraint in the no-brackets case). Jun 19 '06 #47

 P: n/a Keith Thompson wrote: Using a sentinel when reading a file, rather than checking for EOF, is rarely a good idea. [...] I'd say that using a sentinel (or equivalent, e.g. an embedded count) is mandatory when reading a binary stream. How else will you know when you've read all the data -- and only the data? -- Eric Sosman es*****@acm-dot-org.invalid Jun 19 '06 #48

 P: n/a Old Wolf wrote: Richard Heathfield wrote: Ian Collins said: CBFalconer wrote: This code should not compile unless you have a C99 system, which I doubt. Why? Compiles fine with either compiler on mine. If you're using a C99 compiler, well, fair enough. If you're using a compiler adhering to an older standard, like 99.90813774% of us, GCC seems to be the most common compiler around. In its default mode it accepts many C99 constructs. So I think your figure should be revised downwards somewhat. If you disapprove, I suggest you supply an equally precise revised value. Otherwise why criticize the extensive research that has gone into Richards figure? After all, 9 nines precision is not to be sneezed at, and it does imply that Richard has polled at least 10E9 C users. -- "A man who is right every time is not likely to do very much." -- Francis Crick, co-discover of DNA "There is nothing more amazing than stupidity in action." -- Thomas Matthews Jun 19 '06 #49

 P: n/a Eric Sosman writes: Keith Thompson wrote: Using a sentinel when reading a file, rather than checking for EOF, is rarely a good idea. [...] I'd say that using a sentinel (or equivalent, e.g. an embedded count) is mandatory when reading a binary stream. How else will you know when you've read all the data -- and only the data? I'm sure a lot of programs just read the entire file, but I realize the standard allows binary files to be padded with zero bytes. For a file that's just a linear sequence of fixed-size records, reading up to EOF (at the cost of possibly not working on systems that do padding) might be good enough. For anything more complex, the structure of the file itself should tell indicate where the valid data is (are). A sentinel is one of many possible ways to do that. Of course, C strings use '\0' as a sentinel value; the cost is that you can't have '\0' in the string itself. -- Keith Thompson (The_Other_Keith) ks***@mib.org San Diego Supercomputer Center <*> We must do something. This is something. Therefore, we must do this. Jun 19 '06 #50

52 Replies

### This discussion thread is closed

Replies have been disabled for this discussion.