kdq@demott.com (Kevin D. Quitt) (01/05/91)
I originally posted to comp.lang.c++ (don't know how it got there): > What about the subtraction of pointers to get a constant? I discovered >that gcc does not allow: > > int = strchr( string, char ) - &string; > >to determine the position of char within string. Is there a (good) reason >for disallowing this? BTW, Microsoft C *does* accept this. I rapidly received two responses indicating that the & was the problem. (Nobody picked on using int and char as variables :-) The & was "artistic" in my example. Microsoft C does allow &string, but provides a warning that the ampersand is ignored. The actual code is: const unsigned char *chars = "some string" unsigned char pass[]; c = strchr( chars, toupper( pass[ i ]) ) - chars + 1; gcc would not accept this no matter what I did. -- _ Kevin D. Quitt demott!kdq kdq@demott.com DeMott Electronics Co. 14707 Keswick St. Van Nuys, CA 91405-1266 VOICE (818) 988-4975 FAX (818) 997-1190 MODEM (818) 997-4496 PEP last
tim@proton.amd.com (Tim Olson) (01/06/91)
In article <1991Jan5.001607.5915@demott.com> kdq@demott.COM (Kevin D. Quitt) writes: | The actual code is: | | | const unsigned char *chars = "some string" | unsigned char pass[]; | | c = strchr( chars, toupper( pass[ i ]) ) - chars + 1; | | | gcc would not accept this no matter what I did. The problem is the "unsigned" type specifier in the declaration for chars. Section 3.5.4.1 (Pointer declarators) states that For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types. The function "strchr" is defined to return a type "char *"; it is not compatible with "chars", which is of type "unsigned char *". Try removing the "unsigned" specifier from the declaration for "chars", or explicitly cast the result of the strchr() function to (unsigned char *). -- -- Tim Olson Advanced Micro Devices (tim@amd.com)
darcy@druid.uucp (D'Arcy J.M. Cain) (01/06/91)
[I removed comp.lang.c++ from the Newsgroups header as it seems to be only a C question] In article <1991Jan5.001607.5915@demott.com> Kevin D. Quitt writes: >const unsigned char *chars = "some string" >unsigned char pass[]; > c = strchr( chars, toupper( pass[ i ]) ) - chars + 1; > gcc would not accept this no matter what I did. I too have noticed this difference between gcc and Turbo-C. The problem seems to be the "unsigned" part of the declaration of chars. I tried the following: #include <stdio.h> #include <string.h> int main(void) { const char *chars = "some string"; int c; c = strchr(chars, 'e') - chars + 1; return(c); } which compiled without a peep with "gcc -O -Wall tst.c -o tst" but failed when I declared chars as "const unsigned char *chars ...". (it didn't seem to matter whether or not const was used.) The error message is: tst.c: In function main: tst.c:6: warning: initialization between incompatible pointer types tst.c:9: warning: argument passing between incompatible pointer types tst.c:9: invalid operands to binary - tst.c:7: warning: `c' may be used uninitialized in this function So gcc differentiates unsigned char from char. String literals are composed of char objects so their addresses can't be assigned to an unsigned char pointer, strchr() takes a char pointer so an uncasted unsigned char doesn't match the parameter list and char and unsigned char can't be subtracted. So the question is what does ANSI say on the issue. K&R2 seems to support gcc in this. (A2.6, page 194 and A6.6, page 198.) In any case, the snippet you provide doesn't exhibit any reason for using unsigned char over char so perhaps you can just change the declaration. -- D'Arcy J.M. Cain (darcy@druid) | D'Arcy Cain Consulting | There's no government West Hill, Ontario, Canada | like no government! +1 416 281 6094 |
chip@tct.uucp (Chip Salzenberg) (01/08/91)
According to kdq@demott.COM (Kevin D. Quitt): > The actual code is: > > >const unsigned char *chars = "some string" >unsigned char pass[]; > > c = strchr( chars, toupper( pass[ i ]) ) - chars + 1; > > > gcc would not accept this no matter what I did. If strchr() wasn't declared properly, gcc would complain. But a more serious complaint is the lack of a check on the return value of strchr(). It might be NULL, after all, in which case the subtraction will send the resulting value into deep space. -- Chip Salzenberg at Teltronics/TCT <chip@tct.uucp>, <uunet!pdn!tct!chip> "If Usenet exists, then what is its mailing address?" -- me "c/o The Daily Planet, Metropolis." -- Jeff Daiell
rsargent@alias.UUCP (Richard Sargent) (01/08/91)
In article <1991Jan5.001607.5915@demott.com> kdq@demott.COM (Kevin D. Quitt) writes: > >const unsigned char *chars = "some string" >unsigned char pass[]; > > c = strchr( chars, toupper( pass[ i ]) ) - chars + 1; > > One thing that comes to mind is that a *very* fussy compiler, such as gcc with -pedantic (?) turned on, would complain that the difference could be between strings in two different address spaces. This would result in a meaningless difference. Now, by definition, strchr() returns a pointer to within the string (or NULL, I think). But, the compiler may be ignoring what the standard says the function does, and may just consider it as any function returning a pointer to char. In the event that the character is NOT in the string, a NULL return value will result in a meaningless difference. Checking the return value and only taking the difference when non-NULL may be enough. Or maybe the compiler is just too fussy. Or maybe the compiler has a bug. Or ...
gwyn@smoke.brl.mil (Doug Gwyn) (01/09/91)
In article <1991Jan7.173726.1003@alias.uucp> rsargent@alias.UUCP (Richard Sargent) writes: >> c = strchr( chars, toupper( pass[ i ]) ) - chars + 1; >One thing that comes to mind is that a *very* fussy compiler, such >as gcc with -pedantic (?) turned on, would complain that the >difference could be between strings in two different address spaces. The actual error in this code is the mixing of pointers to char and to unsigned char. If the compiler still complains after that error is remedied, then it has a problem. Ensuring that pointer arithmetic involves valid operands in this situation is entirely the programmer's responsibility, not the compiler's. Assuming that everything is declared properly and that the chars string contains all possible runtime values of toupper(...), the above pointer arithmetic (with types fixed) is strictly conforming and thus the C implementation should NOT issue a diagnostic.
volpe@camelback.crd.ge.com (Christopher R Volpe) (01/10/91)
In article <14794@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes: |>The actual error in this code is the mixing of pointers to char and |>to unsigned char. If the compiler still complains after that error |>is remedied, then it has a problem. Ensuring that pointer arithmetic |>involves valid operands in this situation is entirely the programmer's |>responsibility, not the compiler's. Assuming that everything is declared |>properly and that the chars string contains all possible runtime values |>of toupper(...), the above pointer arithmetic (with types fixed) is |>strictly conforming and thus the C implementation should NOT issue a |>diagnostic. I assume you mean "should NOT fail to generate correct code", right? It can, of course, issue a diagnostic if it's raining outside or if it's past 5:00pm on a Friday. ================== Chris Volpe G.E. Corporate R&D volpecr@crd.ge.com
kdq@demott.com (Kevin D. Quitt) (01/10/91)
In article <2788A63D.A86@tct.uucp> chip@tct.uucp (Chip Salzenberg) writes: >If strchr() wasn't declared properly, gcc would complain. > >But a more serious complaint is the lack of a check on the return >value of strchr(). It might be NULL, after all, in which case the >subtraction will send the resulting value into deep space. As I indicated, strchr was not being declared; it's not declared in the same include file as with Microsoft C. I'm used to compilers that complain when things are declared, so I'm used to silence as being a sign that everything's OK. And you're right about checking the return value. This code is a fragment from an encryption package, which is why I had to change it to ask my question. When I get to the line with strchr, I have already guaranteed that the search will not fail. -- _ Kevin D. Quitt demott!kdq kdq@demott.com DeMott Electronics Co. 14707 Keswick St. Van Nuys, CA 91405-1266 VOICE (818) 988-4975 FAX (818) 997-1190 MODEM (818) 997-4496 PEP last
gwyn@smoke.brl.mil (Doug Gwyn) (01/10/91)
In article <15486@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes: >In article <14794@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes: >|>strictly conforming and thus the C implementation should NOT issue a >|>diagnostic. >I assume you mean "should NOT fail to generate correct code", right? >It can, of course, issue a diagnostic if it's raining outside or if >it's past 5:00pm on a Friday. No, I used the term "should not" advisedly. A quality ANSI C implementation should not generate "diagnostics" for a strictly conforming program that are indistinguishable from the ones required by the standard to be generated for violations of syntax rules and constraints. Note that I did not say "must not" (as in the sense that the implementation would not be standard conforming if it did); however, customers have a reasonable right to expect diagnostics to be useful, and spurious ones that announce errors where there are none are an indication of poor product quality. Some people might want the option to generate "warnings" that are readily distinguishable from "error" diagnostics, for example a la UNIX "lint -p"; in the absence of other lint-like support this would be a helpful feature. However, I would hope that such warnings could be easily suppressed, since many legitimate applications of C involve deliberate exploitation of specific features of an implementation. While I strongly discourage unnecessary implementation dependency in application code, there are times when it really is needed.