Why does getenv() work backwards?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Protoman

    Why does getenv() work backwards?

    Why does getenv work backwards? When I'm testing an env variable, I
    have to test if its NOT equal to, rather than equal to, to get the
    desired result. As evidenced by this simple piece of code:

    #include <iostream>
    #include <cstdlib>
    using namespace std;

    const char* cpu=getenv("PRO CESSOR_ARCHITEC TURE");

    int main()
    {
    if(cpu!="x86")
    cout << "Valid " << endl;
    else
    cout << "Invalid " << endl;
    system("PAUSE") ;
    return 0;
    }

    If I use if(cpu=="x86"), I get invalid, which is wrong, but if I use
    if(cpu!="x86), I get valid, which is correct. It's like something is
    backwards here, either with getenv() or WinXP itself. What's going on
    here?

  • danda

    #2
    Re: Why does getenv() work backwards?

    #include <iostream>
    #include <cstdlib>
    using namespace std;

    const char* cpu=getenv("PRO CESSOR_ARCHITEC TURE");

    int main()
    {
    if(cpu!="x86") // this is the problem, don't use != to compare
    cout << "Valid " << endl;
    else
    cout << "Invalid " << endl;
    system("PAUSE") ;
    return 0;

    }

    Comment

    • Matthias Kaeppler

      #3
      Re: Why does getenv() work backwards?

      Protoman wrote:[color=blue]
      > Why does getenv work backwards? When I'm testing an env variable, I
      > have to test if its NOT equal to, rather than equal to, to get the
      > desired result. As evidenced by this simple piece of code:
      >
      > #include <iostream>
      > #include <cstdlib>
      > using namespace std;
      >
      > const char* cpu=getenv("PRO CESSOR_ARCHITEC TURE");
      >
      > int main()
      > {
      > if(cpu!="x86")
      > cout << "Valid " << endl;
      > else
      > cout << "Invalid " << endl;
      > system("PAUSE") ;
      > return 0;
      > }
      >
      > If I use if(cpu=="x86"), I get invalid, which is wrong, but if I use
      > if(cpu!="x86), I get valid, which is correct. It's like something is
      > backwards here, either with getenv() or WinXP itself. What's going on
      > here?
      >[/color]

      This effect is just random I guess. What you're doing is comparing two
      pointers, that is, two addresses, and not the character sequences
      they're pointing to.
      To compare two arrays of char, use strcmp(), or better yet, use
      std::string, that's what we have it for.

      Regards,
      Matthias

      Comment

      • Protoman

        #4
        Re: Why does getenv() work backwards?


        Matthias Kaeppler wrote:[color=blue]
        > Protoman wrote:[color=green]
        > > Why does getenv work backwards? When I'm testing an env variable, I
        > > have to test if its NOT equal to, rather than equal to, to get the
        > > desired result. As evidenced by this simple piece of code:
        > >
        > > #include <iostream>
        > > #include <cstdlib>
        > > using namespace std;
        > >
        > > const char* cpu=getenv("PRO CESSOR_ARCHITEC TURE");
        > >
        > > int main()
        > > {
        > > if(cpu!="x86")
        > > cout << "Valid " << endl;
        > > else
        > > cout << "Invalid " << endl;
        > > system("PAUSE") ;
        > > return 0;
        > > }
        > >
        > > If I use if(cpu=="x86"), I get invalid, which is wrong, but if I use
        > > if(cpu!="x86), I get valid, which is correct. It's like something is
        > > backwards here, either with getenv() or WinXP itself. What's going on
        > > here?
        > >[/color]
        >
        > This effect is just random I guess. What you're doing is comparing two
        > pointers, that is, two addresses, and not the character sequences
        > they're pointing to.
        > To compare two arrays of char, use strcmp(), or better yet, use
        > std::string, that's what we have it for.
        >
        > Regards,
        > Matthias[/color]

        Still, I wonder... Guess I'll just succom to having to think backwards
        with getenv(). And is there anyway I can make sure the program will
        only work if the machine its running on has the same env variable
        values as the machine its compiled on?

        Comment

        • Jacek Dziedzic

          #5
          Re: Why does getenv() work backwards?

          Protoman wrote:
          [color=blue]
          > Still, I wonder... Guess I'll just succom to having to think backwards
          > with getenv().[/color]

          It doesn't work backwards. It's an illusion you get by trying
          to compare char arrays in a way they cannot be compared. Use strcmp().
          [color=blue]
          > And is there anyway I can make sure the program will
          > only work if the machine its running on has the same env variable
          > values as the machine its compiled on?[/color]

          If there is, it's not by comparing pointers and inverting
          the result (what you're currently doing).

          HTH,
          - J.

          Comment

          • Greg

            #6
            Re: Why does getenv() work backwards?

            Protoman wrote:[color=blue]
            > Why does getenv work backwards? When I'm testing an env variable, I
            > have to test if its NOT equal to, rather than equal to, to get the
            > desired result. As evidenced by this simple piece of code:
            >
            > #include <iostream>
            > #include <cstdlib>
            > using namespace std;
            >
            > const char* cpu=getenv("PRO CESSOR_ARCHITEC TURE");[/color]

            Since this is a C++ group let's declare cpu like this:

            const std::string cpu( getenv("PROCESS OR_ARCHITECTURE "));
            [color=blue]
            > int main()
            > {
            > if(cpu!="x86")
            > cout << "Valid " << endl;
            > else
            > cout << "Invalid " << endl;
            > system("PAUSE") ;
            > return 0;
            > }
            >
            > If I use if(cpu=="x86"), I get invalid, which is wrong, but if I use
            > if(cpu!="x86), I get valid, which is correct. It's like something is
            > backwards here, either with getenv() or WinXP itself. What's going on
            > here?[/color]

            With cpu now a std::string the comparison with "x86" will work as you
            think it should, meaning that the strings themselves are being
            compared, not their addresses. This also means that the if-statement
            logic needs to be put back the way it was originally:

            int main()
            {
            if ( cpu=="x86")
            cout << "Valid\n";
            else
            cout << "Invalid \n";
            system("PAUSE") ;
            return 0;
            }

            Greg

            Comment

            • Karl Heinz Buchegger

              #7
              Re: Why does getenv() work backwards?

              Protoman wrote:[color=blue]
              >
              > Still, I wonder... Guess I'll just succom to having to think backwards
              > with getenv(). And is there anyway I can make sure the program will
              > only work if the machine its running on has the same env variable
              > values as the machine its compiled on?[/color]

              What output would you expect in the following:

              #include <iostream>

              int main()
              {
              int* i = new int
              int* j = new int;

              *i = 5;
              *j = 5;

              if( i == j )
              cout << "They are equal\n";
              else
              cout << "They are not equal\n";

              delete i;
              delete j;
              }

              You have done exactly that in your program.
              To fix it, you changed

              if( i == j )

              to

              if( i != j )

              and are now speculating about some backwards logic.
              But the problem is something completely different:
              instead of comparing values

              if( *i == *j )

              you compared pointers

              if( i == j )

              The only difference is, that with C-style strings you
              can't use == for comparing the strings, but have to
              use strcmp to do exactly that: compare if 2 C-style
              strings compare equal by value.

              --
              Karl Heinz Buchegger
              kbuchegg@gascad .at

              Comment

              • Michiel.Salters@tomtom.com

                #8
                Re: Why does getenv() work backwards?

                Greg wrote:[color=blue]
                > Protoman wrote:[/color]
                [color=blue][color=green]
                > > const char* cpu=getenv("PRO CESSOR_ARCHITEC TURE");[/color]
                >
                > Since this is a C++ group let's declare cpu like this:
                >
                > const std::string cpu( getenv("PROCESS OR_ARCHITECTURE "));[/color]

                We really should something like map<string,stri ng> env;' in std,
                so we'd simply say if( std::env["PROCESSOR_ARCH ITECTURE"]=="x86")

                Of course, the return type should be a bit different, else your
                assignments
                to env["X"] won't end up calling setenv( ).

                HTH,
                Michiel Salters

                Comment

                • Andrew Koenig

                  #9
                  Re: Why does getenv() work backwards?

                  "Protoman" <Protoman2050@g mail.com> wrote in message
                  news:1133333736 .056806.204090@ o13g2000cwo.goo glegroups.com.. .
                  [color=blue]
                  > Still, I wonder... Guess I'll just succom to having to think backwards
                  > with getenv().[/color]

                  Nope -- that won't work either.


                  Comment

                  • Protoman

                    #10
                    Re: Why does getenv() work backwards?

                    This is SO confusing

                    Comment

                    • Marcus Kwok

                      #11
                      Re: Why does getenv() work backwards?

                      Protoman <Protoman2050@g mail.com> wrote:[color=blue]
                      > This is SO confusing[/color]

                      *What* is so confusing? Please include context in your replies

                      Run this program and see if you understand what is happening:


                      #include <iostream>
                      #include <cstring>

                      int main()
                      {
                      char* a = "hello";
                      char* b = "hello";

                      if (a == b)
                      std::cout << "pointers: equal\n";
                      else
                      std::cout << "pointers: not equal\n";


                      if (std::strcmp(a, b) == 0)
                      std::cout << "strcmp: equal\n";
                      else
                      std::cout << "strcmp: not equal\n";


                      return 0;
                      }

                      --
                      Marcus Kwok

                      Comment

                      • Ron House

                        #12
                        Re: Why does getenv() work backwards?

                        Protoman wrote:
                        [color=blue]
                        > This is SO confusing[/color]

                        It is actually very simple, but you lack a few facts:

                        1) a C-style string is, grammatically, just an array of char.

                        2) In C/C++, you can NOT compare entire arrays for equality or inequality.

                        therefore:

                        3) You can NOT compare c-style strings for equality or inequality.

                        Now:

                        4) writing the name of any array in an r-value context (such as either
                        side of == or !=), in C/C++, yields, not the array, but rather the
                        address of the array.

                        therefore:

                        5) writing "if (cpu == "x86")" does NOT compare the arrays, but rather
                        it compares the address of the array cpu with the address of the spot
                        where the string literal "x86" is stored; these will NEVER be the same,
                        whether cpu contains "x86" or not, so any hope you have of simple
                        reversing the sense of the test will be in vain.

                        but luckily:

                        6) the designers of C wanted you to be able to compare strings, so

                        7) they invented the strcmp function, yielding an int that is <, ==, or[color=blue]
                        > zero depending on whether the first string is before, the same as, or[/color]
                        after the second alphabetically.

                        therefore

                        8) you should write "if (strcmp(cpu, "x86") == 0)" to test for equality.

                        --
                        Ron House house@usq.edu.a u

                        Ethics website: http://www.sci.usq.edu.au/staff/house/goodness

                        Comment

                        • Michiel.Salters@tomtom.com

                          #13
                          Re: Why does getenv() work backwards?


                          Marcus Kwok wrote:
                          [color=blue]
                          > int main()
                          > {
                          > char* a = "hello";
                          > char* b = "hello";
                          >
                          > if (a == b)
                          > std::cout << "pointers: equal\n";
                          > else
                          > std::cout << "pointers: not equal\n";
                          >
                          >
                          > if (std::strcmp(a, b) == 0)
                          > std::cout << "strcmp: equal\n";
                          > else
                          > std::cout << "strcmp: not equal\n";
                          > }[/color]

                          Bad example - a might be equal to b, or not. Besides, it really should
                          be const char*. If you'd wrote char a[] and char b[], the example would
                          be predictable, and you wouldn't need const.

                          Michiel.

                          Comment

                          • Karl Heinz Buchegger

                            #14
                            Re: Why does getenv() work backwards?

                            Marcus Kwok wrote:[color=blue]
                            >
                            > Protoman <Protoman2050@g mail.com> wrote:[color=green]
                            > > This is SO confusing[/color]
                            >
                            > *What* is so confusing? Please include context in your replies
                            >
                            > Run this program and see if you understand what is happening:
                            >
                            > #include <iostream>
                            > #include <cstring>
                            >
                            > int main()
                            > {
                            > char* a = "hello";
                            > char* b = "hello";
                            >
                            > if (a == b)
                            > std::cout << "pointers: equal\n";
                            > else
                            > std::cout << "pointers: not equal\n";
                            >
                            > if (std::strcmp(a, b) == 0)
                            > std::cout << "strcmp: equal\n";
                            > else
                            > std::cout << "strcmp: not equal\n";
                            >
                            > return 0;
                            > }
                            >[/color]

                            But beware:
                            Actually that program 'might' come up with Protoman's
                            expected output. It all depends on the compiler if it
                            creates 2 string literals "hello" or just one, setting
                            a and b to the same value.

                            --
                            Karl Heinz Buchegger
                            kbuchegg@gascad .at

                            Comment

                            • Niklas Norrthon

                              #15
                              Re: Why does getenv() work backwards?

                              "Protoman" <Protoman2050@g mail.com> writes:
                              [color=blue]
                              > This is SO confusing[/color]

                              What is confusing?

                              Comment

                              Working...