Pointer to int, implicit conversion

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • =?iso-8859-1?b?VG9t4XMg0yBoyWlsaWRoZQ==?=

    Pointer to int, implicit conversion

    [Please forgive the introduction which talks about C++ rather than C, but
    I'd just like to explain how I came to be writing if(p) before I go on to
    tackle C-specific issues]

    Coming originally from C++, I used to do the likes of the following,
    using a pointer in a conditional:


    void Func(int *p)
    {
    if (p)
    {
    *p++ = 7;
    *p++ = 8;
    }
    }

    In C++, the type of conditional expressions is bool. When a pointer
    is converted to bool, it becomes false if it was a null pointer, true
    otherwise. (Let's not get into the issue of whether a pointer to one past
    the last element of an array can compare equal to null :P)

    Now writing C code, I stopped and paused for a moment today when I
    wrote code like that above. It looks to me, that, in the above code, the
    pointer would be converted to an int before it would be evaluated by "if".

    The compiler I'm using on the machine beside me is Microsoft Visual
    Studio, so it's by no means guaranteed to be 100% compliant to any C
    Standard. Anyway, it accepts the above function with zero errors and zero
    warning. (And yes it's in C mode, not C++ mode).

    But my question is:

    1) Should a Standard-compliant compiler accept an implicit conversion
    from pointer type to int? (as in "if (p)")
    2) If so, what exactly is supposed to happen? Do null pointers become
    zero while every other address becomes 1? Somehow I doubt that. My first
    guess would be that the Standard doesn't define the behaviour of
    converting pointers to integer types.

    By the way, I'm aware that the inversion operator, i.e. !, turns a
    null pointer into 1 and every other pointer into 0, but I'm talking
    specifically about a bare naked pointer without an operator applied.

    And yes, I'm fully aware that I can replace if (p) with if (!!p).

    The exact code that had me thinking about this was:

    assert(p);

    I had a function which took a pointer and asserted straight away that
    it actually pointed to something. When I switched to a different compiler
    on a different machine, I got an error telling me there's no implicit
    conversion from pointer to integer type (as I would hope!).

    I think I can recall hearing some time ago that the argument to
    assert MUST be of type int. Is this true? Should I be writing:

    assert(!!p);

    And again, what's supposed to happen when I do assert(p)? Is the
    pointer converted to an int, and then the int evaluated to see if it's
    true or false? If so, then what value does the resultant int have... ? My
    guess is that it's undefined by the Standard.

    --
    Tomás Ó hÉilidhe
  • Francine.Neary@googlemail.com

    #2
    Re: Pointer to int, implicit conversion

    On Nov 20, 7:22 pm, Tomás Ó hÉilidhe <t...@lavabit.c omwrote:
    1) Should a Standard-compliant compiler accept an implicit conversion
    from pointer type to int? (as in "if (p)")
    2) If so, what exactly is supposed to happen? Do null pointers become
    zero while every other address becomes 1? Somehow I doubt that. My first
    guess would be that the Standard doesn't define the behaviour of
    converting pointers to integer types.
    You've asked question 5.3 of the C FAQ. <http://c-faq.com/null/
    ptrtest.html>
    >
    By the way, I'm aware that the inversion operator, i.e. !, turns a
    null pointer into 1 and every other pointer into 0, but I'm talking
    specifically about a bare naked pointer without an operator applied.
    >
    And yes, I'm fully aware that I can replace if (p) with if (!!p).
    >
    The exact code that had me thinking about this was:
    >
    assert(p);
    >
    I had a function which took a pointer and asserted straight away that
    it actually pointed to something. When I switched to a different compiler
    on a different machine, I got an error telling me there's no implicit
    conversion from pointer to integer type (as I would hope!).
    >
    I think I can recall hearing some time ago that the argument to
    assert MUST be of type int. Is this true? Should I be writing:
    >
    assert(!!p);
    >
    And again, what's supposed to happen when I do assert(p)? Is the
    pointer converted to an int, and then the int evaluated to see if it's
    true or false? If so, then what value does the resultant int have... ? My
    guess is that it's undefined by the Standard.
    >
    --
    Tomás Ó hÉilidhe

    Comment

    • =?iso-8859-1?b?VG9t4XMg0yBoyWlsaWRoZQ==?=

      #3
      Re: Pointer to int, implicit conversion

      Francine.Neary:
      You've asked question 5.3 of the C FAQ. <http://c-faq.com/null/
      ptrtest.html>

      Thanks for the link. There's a particular part I want to inquire
      about:

      -- beginning --
      When C requires the Boolean value of an expression, a false value is
      inferred when the expression compares equal to zero, and a true value
      otherwise. That is, whenever one writes

      if(expr)

      where ``expr'' is any expression at all, the compiler essentially acts as
      if it had been written as

      if((expr) != 0)

      --

      Until now, I had thought that if, while and the middle part of a for
      loop all took an "argument" whose type was int. Therefore I _thought_
      that the following would always be identical:

      if (a)

      and:

      if ((int)a)

      , regardless of the type of the expression int. Putting a little more
      thought into it though, I realised I violate this train of thought all
      the time:

      unsigned i = UINT_MAX;

      if (i)

      Of course, the behaviour is implementation-defined when you assign
      too-big-of-a-number to an int, so we can't say for sure whether (int)i
      would be true or false, but we _do_ know for sure that i is true.

      So should I just forget the idea altogether that conditionals are of
      type int in C? I realise that the operators ==, >, !=, etc. all evaluate
      to an int, but I suppose that doesn't have to mean that if, while and the
      middle part of a for have to take an int argument.

      So basically, the conditionals take the value, regardless of its
      type, and return false if it's zero (including a null pointer), otherwise
      true. Looks like I can just keep going exactly how I was doing things in C
      ++. :-D

      If I'm mistaken, please throw a pie in my face! One more thing, can
      someone please tell me whether I have to give an int value to assert?

      --
      Tomás Ó hÉilidhe

      Comment

      • Flash Gordon

        #4
        Re: Pointer to int, implicit conversion

        Tomás Ó hÉilidhe wrote, On 20/11/07 22:36:

        <snip reference to relevant FAQ entry>
        Until now, I had thought that if, while and the middle part of a for
        loop all took an "argument" whose type was int. Therefore I _thought_
        that the following would always be identical:
        >
        if (a)
        >
        and:
        >
        if ((int)a)
        <snip reasons this might be wrong>

        You thought wrong for, amongst other things, the reasons you went on to
        specify.
        So should I just forget the idea altogether that conditionals are of
        type int in C? I realise that the operators ==, >, !=, etc. all evaluate
        to an int, but I suppose that doesn't have to mean that if, while and the
        middle part of a for have to take an int argument.
        Yes, forget that idea as it is definitely wrong.
        So basically, the conditionals take the value, regardless of its
        type, and return false if it's zero (including a null pointer), otherwise
        true. Looks like I can just keep going exactly how I was doing things in C
        ++. :-D
        I believe the rules are the same as for C++ because I believe that C++
        inherited them from C.
        If I'm mistaken, please throw a pie in my face!
        Can't we throw one anyway?
        One more thing, can
        someone please tell me whether I have to give an int value to assert?
        I can't remember the exact rule, but I believe that in C89/C90/C95 (the
        most commonly fully implemented versions of the standard) you are not
        allowed to assert on the value of a pointer directly. I believe this
        changed in C99.
        --
        Flash Gordon

        Comment

        • Jack Klein

          #5
          Re: Pointer to int, implicit conversion

          On Tue, 20 Nov 2007 22:36:03 GMT, Tomás Ó hÉilidhe <toe@lavabit.co m>
          wrote in comp.lang.c:
          Francine.Neary:
          >
          You've asked question 5.3 of the C FAQ. <http://c-faq.com/null/
          ptrtest.html>
          >
          >
          Thanks for the link. There's a particular part I want to inquire
          about:
          >
          -- beginning --
          When C requires the Boolean value of an expression, a false value is
          inferred when the expression compares equal to zero, and a true value
          otherwise. That is, whenever one writes
          >
          if(expr)
          >
          where ``expr'' is any expression at all, the compiler essentially acts as
          if it had been written as
          >
          if((expr) != 0)
          >
          --
          >
          Until now, I had thought that if, while and the middle part of a for
          loop all took an "argument" whose type was int. Therefore I _thought_
          that the following would always be identical:
          >
          if (a)
          >
          and:
          >
          if ((int)a)
          >
          , regardless of the type of the expression int. Putting a little more
          thought into it though, I realised I violate this train of thought all
          the time:
          >
          unsigned i = UINT_MAX;
          >
          if (i)
          >
          Of course, the behaviour is implementation-defined when you assign
          too-big-of-a-number to an int, so we can't say for sure whether (int)i
          would be true or false, but we _do_ know for sure that i is true.
          >
          So should I just forget the idea altogether that conditionals are of
          type int in C? I realise that the operators ==, >, !=, etc. all evaluate
          to an int, but I suppose that doesn't have to mean that if, while and the
          middle part of a for have to take an int argument.
          An expression evaluated in a Boolean context in C yields a result of
          type int with the value 0 or 1. That has nothing to do with what the
          operands are.

          For example:

          double d1 = 3.9 d2 = 3.1;

          if (d1 == d2)
          {
          /* stuff */
          }

          I assume that if you wrote the code above, you would be very, very
          surprised if the statements designated by /* stuff */ were executed.
          Yet if there was an explicit conversion to int, both d1 and d2 would
          be truncated to 3, and /* stuff */ would be executed.
          So basically, the conditionals take the value, regardless of its
          type, and return false if it's zero (including a null pointer), otherwise
          true. Looks like I can just keep going exactly how I was doing things in C
          ++. :-D
          Basically, expressions operate on values. If there are multiple
          values, rvalues or lvalues, in an expression, the standard promotions
          are performed, just as if you perform an operation like addition or
          subtraction on two different types.

          Based on the as-if rule, of course, Boolean expressions do not
          actually have to produce an actual int with a value of 0 or 1. In the
          d1 and d2 example above, the compiler generates machine language to do
          the comparison and uses some processor specific mechanism to execute
          /* stuff */ or jump over it.

          On the other hand, if you have code like this (inside a function):

          double d1 = /* some value */, d2 = /* some value */;
          int equal;

          /* some operations that might modify the values of */
          /* d1 and/or d2 */

          equal = (d1 == d2);

          ....then the program must generate code to produce an actual int value
          of 0 or 1 and store it in "equal". Assuming that it the value of
          equal is later used, so it can't be optimized away.
          If I'm mistaken, please throw a pie in my face! One more thing, can
          someone please tell me whether I have to give an int value to assert?
          Flash's memory on this question is correct. Prior to C99, the C
          standard defined the assert macro to take an int parameter, although
          many (perhaps even most) compilers accepted a pointer with an implicit
          test against 0.

          From 1999 on, the C standard allows any scalar type for the
          expression, meaning integer types, floating point types, and pointers.

          --
          Jack Klein
          Home: http://JK-Technology.Com
          FAQs for
          comp.lang.c http://c-faq.com/
          comp.lang.c++ http://www.parashift.com/c++-faq-lite/
          alt.comp.lang.l earn.c-c++

          Comment

          • James Kuyper

            #6
            Re: Pointer to int, implicit conversion

            Tomás Ó hÉilidhe wrote:
            ....
            So basically, the conditionals take the value, regardless of its
            type, and return false if it's zero (including a null pointer), otherwise
            Conditionals do not return false (or true); they result in one part of
            the code or another being executed. They do this based upon whether or
            not the conditional expression compares equal to 0. That's not the same
            as saying it's the same as 0. An expression can be zero only if it has
            arithmetic type. Pointers do not have an arithmetic type, so it's not
            meaningful to say that they are 0, but because of the rules for null
            pointer constants, pointers compare equal to zero when they are null.

            Comment

            • Rakesh UV

              #7
              Re: Pointer to int, implicit conversion

              On Nov 21, 9:36 am, James Kuyper <jameskuy...@ve rizon.netwrote:
              Tomás Ó hÉilidhe wrote:
              >
              ...
              >
              So basically, the conditionals take the value, regardless of its
              type, and return false if it's zero (including a null pointer), otherwise
              >
              Conditionals do not return false (or true); they result in one part of
              the code or another being executed. They do this based upon whether or
              not the conditional expression compares equal to 0. That's not the same
              as saying it's the same as 0. An expression can be zero only if it has
              arithmetic type. Pointers do not have an arithmetic type, so it's not
              meaningful to say that they are 0, but because of the rules for null
              pointer constants, pointers compare equal to zero when they are null.
              If You are working in a 64 bit machine then it would make a difference
              otherwise if(p) doesn't have any issue in 32 bit machine
              If we really want to use a language efficiently and safely, Then we
              should
              try to express our intension much clearly and specifically in C
              language.
              instead of allowing the compiler to assume thing, this a very bad
              Practice.
              This discussion was not useful and was repitative

              RUV

              Comment

              • Chris Torek

                #8
                Re: Pointer to int, implicit conversion

                In article <njJ0j.23309$j7 .443441@news.in digo.ie>
                Tomás Ó hÉilidhe <toe@lavabit.co mwrote:
                [snippage]
                Until now, I had thought that if, while and the middle part of a for
                >loop all took an "argument" whose type was int. ...
                If they were functions, they would take actual arguments, and --
                assuming they were not something peculiar like printf(), i.e.,
                not a "variadic" function -- the argument would have to have a
                fixed type. But they are not functions; they are keywords.

                The way to think about them, in my opinion -- which I admit is
                a bit colored by past work on compilers -- is to say that they
                take an "expression tree node", which is a compiler internal
                data structure, and start by examining the type of this node.
                If the type is "pointer to T" (where T is any valid type -- if
                T were not a valid type we would not have gotten to this point
                inside the compiler in the first place), they generate code to
                compare the pointer against a null pointer of that same type.

                If the expression tree node has some other type, such as "double",
                the compiler generates a comparison against 0.0, or whatever else
                is appropriate. If the node has a type that is already known to
                be "sufficient ly boolean", whatever that means given the compiler
                and the target architecture, the compiler may not have to generate
                any code at all. (As an example of the latter, if the node is not
                a simple variable, but instead is something like (COMPAREOP x y),
                the compiler need only ask its expression-evaluator to generate
                the appropriate comparison-for-condition-codes sequence, then emit
                the appropriate branch. This assumes the target CPU has condition
                codes, of course.)
                --
                In-Real-Life: Chris Torek, Wind River Systems
                Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
                email: forget about it http://web.torek.net/torek/index.html
                Reading email is like searching for food in the garbage, thanks to spammers.

                Comment

                • santosh

                  #9
                  Re: Pointer to int, implicit conversion

                  In article
                  <a3cb9555-e9ad-479d-841d-a83789cb22a4@c3 0g2000hsa.googl egroups.com>,
                  Rakesh UV <uvrakesh@gmail .comwrote on Wednesday 21 Nov 2007 12:59 pm:
                  On Nov 21, 9:36 am, James Kuyper <jameskuy...@ve rizon.netwrote:
                  >Tomás Ó hÉilidhe wrote:
                  >>
                  >...
                  >>
                  So basically, the conditionals take the value, regardless of
                  its
                  type, and return false if it's zero (including a null pointer),
                  otherwise
                  >>
                  >Conditionals do not return false (or true); they result in one part
                  >of the code or another being executed. They do this based upon
                  >whether or not the conditional expression compares equal to 0. That's
                  >not the same as saying it's the same as 0. An expression can be zero
                  >only if it has arithmetic type. Pointers do not have an arithmetic
                  >type, so it's not meaningful to say that they are 0, but because of
                  >the rules for null pointer constants, pointers compare equal to zero
                  >when they are null.
                  >
                  If You are working in a 64 bit machine then it would make a difference
                  otherwise
                  What would make a difference? Comparing pointers against literal zero?
                  If so, I can't see why?
                  if(p) doesn't have any issue in 32 bit machine
                  I believe it should be issue-free on any N-bit system that supports
                  Standard C.
                  If we really want to use a language efficiently and safely, Then we
                  should try to express our intension much clearly and specifically in C
                  language. instead of allowing the compiler to assume thing,
                  I agree here. Compilers can handle obscure and "clever" constructs and
                  obfuscated code, but the maintenance programmer may not do so. High
                  level language source is for human consumption, otherwise we might as
                  well program in machine code.
                  this a very bad Practice.
                  This discussion was not useful and was
                  repitative
                  It's likely to be useful to lurkers and newbies, who are perhaps the
                  greatest beneficiaries of most newsgroups.

                  Comment

                  • =?iso-8859-1?b?VG9t4XMg0yBoyWlsaWRoZQ==?=

                    #10
                    Re: Pointer to int, implicit conversion

                    Jack Klein:
                    For example:
                    >
                    double d1 = 3.9 d2 = 3.1;
                    >
                    if (d1 == d2)
                    {
                    /* stuff */
                    }
                    >
                    I assume that if you wrote the code above, you would be very, very
                    surprised if the statements designated by /* stuff */ were executed. Yet
                    if there was an explicit conversion to int, both d1 and d2 would be
                    truncated to 3, and /* stuff */ would be executed.

                    That would never happen. If I had:

                    void Func(int);

                    and called it as follows:

                    Func( 2.0 * 3.7 );

                    , then the entire expression would be converted to int _after_ it's
                    evaluated. It won't becomes "2 * 3".

                    (Somehow I think we misunderstand each other here because I've read a few
                    of your other posts and you seem to know your stuff, so it's surprising
                    to me that you'd come out with something like this).

                    --
                    Tomás Ó hÉilidhe

                    Comment

                    • Philip Potter

                      #11
                      Re: Pointer to int, implicit conversion

                      Tomás Ó hÉilidhe wrote:
                      Jack Klein:
                      >
                      >For example:
                      >>
                      >double d1 = 3.9 d2 = 3.1;
                      >>
                      > if (d1 == d2)
                      > {
                      > /* stuff */
                      > }
                      >>
                      >I assume that if you wrote the code above, you would be very, very
                      >surprised if the statements designated by /* stuff */ were executed. Yet
                      >if there was an explicit conversion to int, both d1 and d2 would be
                      >truncated to 3, and /* stuff */ would be executed.
                      >
                      That would never happen. If I had:
                      You're right, but the following demonstrates the same point:

                      if(d1 - d2) /* same values as before */
                      {
                      /* stuff */
                      }

                      i.e. if(0.8) is true because 0.8 != 0.0; it is not false because
                      (int)0.8 == 0.

                      Comment

                      • James Kuyper

                        #12
                        Re: Pointer to int, implicit conversion

                        Rakesh UV wrote:
                        On Nov 21, 9:36 am, James Kuyper <jameskuy...@ve rizon.netwrote:
                        >Tomás Ó hÉilidhe wrote:
                        ....
                        >> So basically, the conditionals take the value, regardless of its
                        >>type, and return false if it's zero (including a null pointer), otherwise
                        >>
                        >Conditionals do not return false (or true); they result in one part of
                        >the code or another being executed. They do this based upon whether or
                        >not the conditional expression compares equal to 0. That's not the same
                        >as saying it's the same as 0. An expression can be zero only if it has
                        >arithmetic type. Pointers do not have an arithmetic type, so it's not
                        >meaningful to say that they are 0, but because of the rules for null
                        >pointer constants, pointers compare equal to zero when they are null.
                        >
                        If You are working in a 64 bit machine then it would make a difference
                        Explain, please?
                        otherwise if(p) doesn't have any issue in 32 bit machine
                        As far as I know, the only issue with if(p) is whether or not the
                        programmer correctly understands that it is identical in meaning to
                        if(p!=0). I don't see how that depends upon whether the machine is 32
                        bits or 64 bits.
                        If we really want to use a language efficiently and safely, Then we
                        should
                        try to express our intension much clearly and specifically in C
                        language.
                        If(p) seems perfectly clear to me.
                        instead of allowing the compiler to assume thing, this a very bad
                        Practice.
                        What assumption are you talking about?

                        Comment

                        • Richard

                          #13
                          Re: Pointer to int, implicit conversion

                          Tomás Ó hÉilidhe <toe@lavabit.co mwrites:
                          Jack Klein:
                          >
                          >For example:
                          >>
                          >double d1 = 3.9 d2 = 3.1;
                          >>
                          > if (d1 == d2)
                          > {
                          > /* stuff */
                          > }
                          >>
                          >I assume that if you wrote the code above, you would be very, very
                          >surprised if the statements designated by /* stuff */ were executed. Yet
                          >if there was an explicit conversion to int, both d1 and d2 would be
                          >truncated to 3, and /* stuff */ would be executed.
                          >
                          >
                          That would never happen. If I had:
                          >
                          void Func(int);
                          >
                          and called it as follows:
                          >
                          Func( 2.0 * 3.7 );
                          >
                          , then the entire expression would be converted to int _after_ it's
                          evaluated. It won't becomes "2 * 3".
                          >
                          (Somehow I think we misunderstand each other here because I've read a few
                          of your other posts and you seem to know your stuff, so it's surprising
                          to me that you'd come out with something like this).
                          You appear to have missed the bit where he said

                          "if there was an explicit conversion to int" where I assume Jack was
                          referring to d1 and d2 being explicitly cast. "if" being the operative
                          word here.



                          Comment

                          • =?iso-8859-1?b?VG9t4XMg0yBoyWlsaWRoZQ==?=

                            #14
                            Re: Pointer to int, implicit conversion

                            Richard:
                            You appear to have missed the bit where he said
                            >
                            "if there was an explicit conversion to int" where I assume Jack was
                            referring to d1 and d2 being explicitly cast. "if" being the operative
                            word here.

                            I didn't miss it. Even if there were a conversion to int, it would be:

                            (int)(d1 == d2)

                            rather than:

                            (int)d1 == (int)d2

                            --
                            Tomás Ó hÉilidhe

                            Comment

                            • Jack Klein

                              #15
                              Re: Pointer to int, implicit conversion

                              On Wed, 21 Nov 2007 18:15:53 GMT, Tomás Ó hÉilidhe <toe@lavabit.co m>
                              wrote in comp.lang.c:
                              Richard:
                              >
                              You appear to have missed the bit where he said

                              "if there was an explicit conversion to int" where I assume Jack was
                              referring to d1 and d2 being explicitly cast. "if" being the operative
                              word here.
                              >
                              >
                              I didn't miss it. Even if there were a conversion to int, it would be:
                              >
                              (int)(d1 == d2)
                              >
                              rather than:
                              >
                              (int)d1 == (int)d2
                              Then we were misunderstandin g each other, my example assumed you were
                              thinking of the latter, when apparently you were not.

                              --
                              Jack Klein
                              Home: http://JK-Technology.Com
                              FAQs for
                              comp.lang.c http://c-faq.com/
                              comp.lang.c++ http://www.parashift.com/c++-faq-lite/
                              alt.comp.lang.l earn.c-c++

                              Comment

                              Working...