Portable and ok?

Discussion in 'C Programming' started by pemo, Nov 2, 2005.

  1. pemo

    pemo Guest

    /*
    ** input: an integer [value]. In the range. 0 - 15.
    **
    ** return: if in range, the character that encodes the value
    ** passed as a hex char - else - NULL.
    */
    char itoh(int n)
    {
    return n < 0 || n > 15 ? NULL : "0123456789ABCDEF"[n];
    }
     
    pemo, Nov 2, 2005
    #1
    1. Advertising

  2. On 2005-11-02 07:32:30 -0500, "pemo" <> said:

    > /*
    > ** input: an integer [value]. In the range. 0 - 15.
    > **
    > ** return: if in range, the character that encodes the value
    > ** passed as a hex char - else - NULL.
    > */
    > char itoh(int n)
    > {
    > return n < 0 || n > 15 ? NULL : "0123456789ABCDEF"[n];
    > }


    The only part of that that isn't portable is the attempt to convert
    NULL to a char. However, if you were asking about the
    ("0123456789ABCDEF"[n]) part, that's fine. I would rewrite that
    function as:

    char itoh(int n)
    {
    return n < 0 || n > 15 ? 0 : "0123456789ABCDEF"[n];
    }


    --
    Clark S. Cox, III
     
    Clark S. Cox III, Nov 2, 2005
    #2
    1. Advertising

  3. pemo wrote:
    > /*
    > ** input: an integer [value]. In the range. 0 - 15.
    > **
    > ** return: if in range, the character that encodes the value
    > ** passed as a hex char - else - NULL.
    > */
    > char itoh(int n)
    > {
    > return n < 0 || n > 15 ? NULL : "0123456789ABCDEF"[n];
    > }


    Why null? Why not return 0?

    IIRC NULL is allowed to be defined as (void *) 0, which could cause
    problems with your code.
     
    Antonio Contreras, Nov 2, 2005
    #3
  4. pemo

    Skarmander Guest

    pemo wrote:
    > /*
    > ** input: an integer [value]. In the range. 0 - 15.
    > **
    > ** return: if in range, the character that encodes the value
    > ** passed as a hex char - else - NULL.
    > */
    > char itoh(int n)
    > {
    > return n < 0 || n > 15 ? NULL : "0123456789ABCDEF"[n];
    > }
    >
    >


    No. Conversion from NULL to a char is undefined. I recommend returning
    '?' instead, or triggering an assertion or other exception mechanism to
    handle the problem.

    Returning NUL ('\0') is also a possibility, but one I would avoid, since
    it would likely lead to mysteriously truncated strings.

    S.
     
    Skarmander, Nov 2, 2005
    #4
  5. pemo

    Dick de Boer Guest

    "pemo" <> wrote in message
    news:dkabl0$hc9$...
    > /*
    > ** input: an integer [value]. In the range. 0 - 15.
    > **
    > ** return: if in range, the character that encodes the value
    > ** passed as a hex char - else - NULL.
    > */
    > char itoh(int n)
    > {
    > return n < 0 || n > 15 ? NULL : "0123456789ABCDEF"[n];
    > }
    >
    >

    For n out of range:
    NULL is a pointer, not a char. In this code, the NULL will be converted to a
    char, and *if* NULL equals zero, the return value will be zero. If NULL
    equals not zero but for instance (void*)-1, the value 255 will be returned.
    If the char is unsigned by default (implementation defined), this will never
    compare equal with NULL.

    So, NOT portable.

    DickB
     
    Dick de Boer, Nov 2, 2005
    #5
  6. pemo

    Chris Dollin Guest

    pemo wrote:

    > /*
    > ** input: an integer [value]. In the range. 0 - 15.
    > **
    > ** return: if in range, the character that encodes the value
    > ** passed as a hex char - else - NULL.


    [For NUL read `some sensible error-character`.]

    Your description is inconsistent: if the value is in the range
    0..15, then there's no need for a NUL error-value; if you need
    the NUL error-value, you don't need the restriction 0 - 15.

    Since your code handles the general case, I'd suggest

    input: an integer N.
    return: if 0 <= N <= 15, the corresponding hex character;
    otherwise, NUL.

    --
    Chris "eccentric hedgehog" Dollin
    Is it time for a November Project?
     
    Chris Dollin, Nov 2, 2005
    #6
  7. pemo wrote:
    [Repeated from subject line, where it was wrongly tucked away:
    Subject: Portable and ok?]

    No, it's not OK. Don't use pointers for integer values even if you have
    every reason to think it will work. Why are you avoiding using 0 when
    you mean 0?

    > /*
    > ** input: an integer [value]. In the range. 0 - 15.
    > **
    > ** return: if in range, the character that encodes the value
    > ** passed as a hex char - else - NULL.

    ^^^^ 0
    > */
    > char itoh(int n)
    > {
    > return n < 0 || n > 15 ? NULL : "0123456789ABCDEF"[n];

    ^^^^ 0
    > }
    >
    >
     
    Martin Ambuhl, Nov 2, 2005
    #7
  8. pemo

    Flash Gordon Guest

    Dick de Boer wrote:
    > "pemo" <> wrote in message
    > news:dkabl0$hc9$...
    >
    >>/*
    >>** input: an integer [value]. In the range. 0 - 15.
    >>**
    >>** return: if in range, the character that encodes the value
    >>** passed as a hex char - else - NULL.
    >>*/
    >>char itoh(int n)
    >>{
    >> return n < 0 || n > 15 ? NULL : "0123456789ABCDEF"[n];
    >>}

    >
    > For n out of range:
    > NULL is a pointer, not a char. In this code, the NULL will be converted to a
    > char, and *if* NULL equals zero, the return value will be zero. If NULL
    > equals not zero but for instance (void*)-1,


    Highly unlikely. (void*)0 and ((void*)0) are likely, but (void*)-1 is
    *very* unlikely. The reason being that (void*)0 is *required* to produce
    a null pointer, but (void*)-1 is not.

    > the value 255 will be returned.
    > If the char is unsigned by default (implementation defined), this will never
    > compare equal with NULL.


    If NULL is defined as (void*)anything then the compiler is *required* to
    produce a diagnostic because pointers cannot be implicitly converted to
    integer types. *If* it produced an executable, which it would not be
    required to, then it could return anything it wanted.

    > So, NOT portable.


    True.
    --
    Flash Gordon
    Living in interesting times.
    Although my email address says spam, it is real and I read it.
     
    Flash Gordon, Nov 2, 2005
    #8
  9. pemo

    Jordan Abel Guest

    On 2005-11-02, Flash Gordon <> wrote:
    > Dick de Boer wrote:
    >> "pemo" <> wrote in message
    >> news:dkabl0$hc9$...
    >>
    >>>/*
    >>>** input: an integer [value]. In the range. 0 - 15.
    >>>**
    >>>** return: if in range, the character that encodes the value
    >>>** passed as a hex char - else - NULL.
    >>>*/
    >>>char itoh(int n)
    >>>{
    >>> return n < 0 || n > 15 ? NULL : "0123456789ABCDEF"[n];
    >>>}

    >>
    >> For n out of range:
    >> NULL is a pointer, not a char. In this code, the NULL will be converted to a
    >> char, and *if* NULL equals zero, the return value will be zero. If NULL
    >> equals not zero but for instance (void*)-1,

    >
    > Highly unlikely. (void*)0 and ((void*)0) are likely, but (void*)-1 is
    > *very* unlikely. The reason being that (void*)0 is *required* to produce
    > a null pointer, but (void*)-1 is not.


    ok, suppose "null pointers are all-bits-1". There's no guarantee that
    converting a null pointer back to an int will yield a 0.
     
    Jordan Abel, Nov 2, 2005
    #9
  10. pemo

    Flash Gordon Guest

    Jordan Abel wrote:
    > On 2005-11-02, Flash Gordon <> wrote:


    <snip>

    >>Highly unlikely. (void*)0 and ((void*)0) are likely, but (void*)-1 is
    >>*very* unlikely. The reason being that (void*)0 is *required* to produce
    >>a null pointer, but (void*)-1 is not.

    >
    > ok, suppose "null pointers are all-bits-1". There's no guarantee that
    > converting a null pointer back to an int will yield a 0.


    Yes, I completely agree.
    --
    Flash Gordon
    Living in interesting times.
    Although my email address says spam, it is real and I read it.
     
    Flash Gordon, Nov 2, 2005
    #10
  11. Jordan Abel <> writes:
    > On 2005-11-02, Flash Gordon <> wrote:
    >> Dick de Boer wrote:
    >>> "pemo" <> wrote in message
    >>> news:dkabl0$hc9$...
    >>>
    >>>>/*
    >>>>** input: an integer [value]. In the range. 0 - 15.
    >>>>**
    >>>>** return: if in range, the character that encodes the value
    >>>>** passed as a hex char - else - NULL.
    >>>>*/
    >>>>char itoh(int n)
    >>>>{
    >>>> return n < 0 || n > 15 ? NULL : "0123456789ABCDEF"[n];
    >>>>}
    >>>
    >>> For n out of range:
    >>> NULL is a pointer, not a char. In this code, the NULL will be
    >>> converted to a char, and *if* NULL equals zero, the return value
    >>> will be zero. If NULL equals not zero but for instance (void*)-1,

    >>
    >> Highly unlikely. (void*)0 and ((void*)0) are likely, but (void*)-1 is
    >> *very* unlikely. The reason being that (void*)0 is *required* to produce
    >> a null pointer, but (void*)-1 is not.

    >
    > ok, suppose "null pointers are all-bits-1". There's no guarantee that
    > converting a null pointer back to an int will yield a 0.


    Certainly -- but note that the code we're discussing uses a null
    pointer constant, not (necessarily) a null pointer. If the
    implementation uses all-bits-1 for null pointers, NULL could still be
    defined as 0; it would result in all-bits-1 if converted to a pointer
    type, but would still act as a plain integer constant 0 if it's not
    converted to a pointer type.

    On the other hand, if NULL is defined as ((void*)0), it would *still*
    result in all-bits-1 if coverted to a pointer type, but it must
    trigger a diagnostic if used as above.

    Even if an implementation uses something other than all-bits-zero for
    null pointers, that doesn't affect the definition of a null pointer
    constant (something that exists only in program source), and it's not
    likely to affect the definition of NULL.

    I think the OP has two problems. First, he's incorrectly assuming
    that NULL refers to a null character rather than a null pointer
    constant. Second, he's probably using an implementation that defines
    NULL as 0, so it isn't catching the error.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Nov 2, 2005
    #11
  12. pemo

    Simon Biber Guest

    Martin Ambuhl wrote:
    > pemo wrote:
    > [Repeated from subject line, where it was wrongly tucked away:
    > Subject: Portable and ok?]
    >
    > No, it's not OK. Don't use pointers for integer values even if you have
    > every reason to think it will work. Why are you avoiding using 0 when
    > you mean 0?


    Since the OP doesn't appear to be participating in this thread, allow me
    to hazard a guess:

    - don't know the difference between a null pointer and a null character

    - the teacher said to *never* use literal values

    - thought it possible that null may not be zero, better use the macro
    to be sure

    Unfortunately, in my experience very few teachers accurately teach the
    difference between a null pointer, a null pointer constant and a null
    character.

    --
    Simon.
     
    Simon Biber, Nov 2, 2005
    #12
  13. pemo

    Jordan Abel Guest

    On 2005-11-02, Simon Biber <> wrote:
    > - the teacher said to *never* use literal values
    >
    > - thought it possible that null may not be zero, better use the macro
    > to be sure


    in either of those two cases, the appropriate way would be '\0'
     
    Jordan Abel, Nov 2, 2005
    #13
  14. Jordan Abel <> writes:
    > On 2005-11-02, Simon Biber <> wrote:
    >> - the teacher said to *never* use literal values
    >>
    >> - thought it possible that null may not be zero, better use the macro
    >> to be sure

    >
    > in either of those two cases, the appropriate way would be '\0'


    Um, '\0' is a literal value.

    Of course, there's absolutely nothing wrong with using a literal '\0'
    where it's appropriate. *If* the teacher said never to use literal
    values, it's very bad advice -- but of course we have no direct
    evidence that the teacher said so.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Nov 2, 2005
    #14
  15. pemo

    Jordan Abel Guest

    On 2005-11-02, Keith Thompson <> wrote:
    > Jordan Abel <> writes:
    >> On 2005-11-02, Simon Biber <> wrote:
    >>> - the teacher said to *never* use literal values
    >>>
    >>> - thought it possible that null may not be zero, better use
    >>> the macro to be sure

    >>
    >> in either of those two cases, the appropriate way would be '\0'

    >
    > Um, '\0' is a literal value.


    So is the string he has with the hex digits - there's very little
    you can do without literal values of any kind - i think the most
    complicated program you can implement is echo.

    > Of course, there's absolutely nothing wrong with using a literal
    > '\0' where it's appropriate. *If* the teacher said never to use
    > literal values, it's very bad advice -- but of course we have no
    > direct evidence that the teacher said so.
    >
     
    Jordan Abel, Nov 2, 2005
    #15
  16. Jordan Abel <> writes:
    > On 2005-11-02, Keith Thompson <> wrote:
    >> Jordan Abel <> writes:
    >>> On 2005-11-02, Simon Biber <> wrote:
    >>>> - the teacher said to *never* use literal values
    >>>>
    >>>> - thought it possible that null may not be zero, better use
    >>>> the macro to be sure
    >>>
    >>> in either of those two cases, the appropriate way would be '\0'

    >>
    >> Um, '\0' is a literal value.

    >
    > So is the string he has with the hex digits - there's very little
    > you can do without literal values of any kind - i think the most
    > complicated program you can implement is echo.


    Aha, a challenge!

    Without using literals, you can easily construct constant expressions
    for any integer you like:

    static int dummy;
    #define ZERO (&dummy!=&dummy)
    #define ONE (&dummy==&dummy)
    #define TWO (ONE+ONE)
    #define THREE (TWO+ONE)
    #define FOUR (THREE+ONE)

    Character and string literals are a bit more difficult. You can
    construct anything you like if you're willing to assume an ASCII
    encoding, but that's cheating. I think you can determine the values
    of '0' through '9' by looping over the range 0 .. SCHAR_MAX and
    checking isdigit(). You can do the same thing for letters by checking
    isupper() and islower(); this works for both ASCII and EBCDIC, but not
    for any character sets in which the letters aren't in alphabetical
    order. (The results won't be constant expressions unless you go to a
    *lot* of extra effort.)

    fopen() is difficult because the mode argument is usually a string
    literal. It doesn't have to be a constant, but I can't think of a
    good way to generate an 'r' or 'w' character.

    printf(), of course, requires a format string. It can be built up
    manually if you can construct the required characters.

    Just to be clear (and because I've criticized others for not including
    this disclaimer), this is absolutely nothing more than a silly little
    intellectual exercise, of no actual use that I can think of. And I
    haven't had a homework assignment in decades.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Nov 3, 2005
    #16
  17. pemo

    Jordan Abel Guest

    On 2005-11-03, Keith Thompson <> wrote:
    > Jordan Abel <> writes:
    >> So is the string he has with the hex digits - there's very little
    >> you can do without literal values of any kind - i think the most
    >> complicated program you can implement is echo.

    >
    > Aha, a challenge!
    >
    > Without using literals, you can easily construct constant expressions
    > for any integer you like:


    [snip other stuff]

    geez - it'd be easier to program in brainf***
     
    Jordan Abel, Nov 3, 2005
    #17
  18. "Clark S. Cox III" wrote:
    >
    > On 2005-11-02 07:32:30 -0500, "pemo" <> said:
    >
    > > /*
    > > ** input: an integer [value]. In the range. 0 - 15.
    > > **
    > > ** return: if in range, the character that encodes the value
    > > ** passed as a hex char - else - NULL.
    > > */
    > > char itoh(int n)
    > > {
    > > return n < 0 || n > 15 ? NULL : "0123456789ABCDEF"[n];
    > > }

    >
    > The only part of that that isn't portable is the attempt to convert
    > NULL to a char. However, if you were asking about the
    > ("0123456789ABCDEF"[n]) part, that's fine. I would rewrite that
    > function as:
    >
    > char itoh(int n)
    > {
    > return n < 0 || n > 15 ? 0 : "0123456789ABCDEF"[n];
    > }


    And, for clarity, I would make a minor change:

    char itoh(int n)
    {
    return (n < 0 || n > 15) ? '\0' : "0123456789ABCDEF"[n];
    }

    --
    +-------------------------+--------------------+-----------------------------+
    | Kenneth J. Brody | www.hvcomputer.com | |
    | kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
    +-------------------------+--------------------+-----------------------------+
    Don't e-mail me at: <mailto:>
     
    Kenneth Brody, Nov 3, 2005
    #18
  19. Keith Thompson wrote:
    >
    > Jordan Abel <> writes:
    > > On 2005-11-02, Simon Biber <> wrote:
    > >> - the teacher said to *never* use literal values
    > >>
    > >> - thought it possible that null may not be zero, better use the macro
    > >> to be sure

    > >
    > > in either of those two cases, the appropriate way would be '\0'

    >
    > Um, '\0' is a literal value.
    >
    > Of course, there's absolutely nothing wrong with using a literal '\0'
    > where it's appropriate. *If* the teacher said never to use literal
    > values, it's very bad advice -- but of course we have no direct
    > evidence that the teacher said so.


    And if the teacher really said never use literal values, then you can't
    use the literal "0123456789ABCDEF", either. In fact, you couldn't even
    use "%x" to pass to sprintf.

    Unless you're allow to use

    #define MyHexString "0123456789ABCDEF"

    But, I guess this depends on how picky the teacher is.

    --
    +-------------------------+--------------------+-----------------------------+
    | Kenneth J. Brody | www.hvcomputer.com | |
    | kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
    +-------------------------+--------------------+-----------------------------+
    Don't e-mail me at: <mailto:>
     
    Kenneth Brody, Nov 3, 2005
    #19
  20. pemo

    tedu Guest

    Keith Thompson wrote:
    > fopen() is difficult because the mode argument is usually a string
    > literal. It doesn't have to be a constant, but I can't think of a
    > good way to generate an 'r' or 'w' character.


    const char *r() { return __func__; }
     
    tedu, Nov 3, 2005
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Eli Bendersky
    Replies:
    1
    Views:
    1,171
    Mike Treseler
    Mar 1, 2006
  2. =?Utf-8?B?c3VyZXNoX0Mj?=
    Replies:
    8
    Views:
    7,416
    =?Utf-8?B?TWFoZXNoIE5pbWJhbGthcg==?=
    May 3, 2005
  3. DonBot
    Replies:
    1
    Views:
    500
    Peter Koch Larsen
    Feb 8, 2005
  4. Interactive AND Portable?

    , Oct 30, 2003, in forum: C Programming
    Replies:
    22
    Views:
    718
  5. Replies:
    7
    Views:
    921
Loading...

Share This Page