Why does getenv() work backwards?

Discussion in 'C++' started by Protoman, Nov 30, 2005.

  1. Protoman

    Protoman Guest

    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("PROCESSOR_ARCHITECTURE");

    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?
    Protoman, Nov 30, 2005
    #1
    1. Advertising

  2. Protoman

    danda Guest

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

    const char* cpu=getenv("PROCESSOR_ARCHITECTURE");

    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;

    }
    danda, Nov 30, 2005
    #2
    1. Advertising

  3. Protoman wrote:
    > 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("PROCESSOR_ARCHITECTURE");
    >
    > 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?
    >


    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
    Matthias Kaeppler, Nov 30, 2005
    #3
  4. Protoman

    Protoman Guest

    Matthias Kaeppler wrote:
    > Protoman wrote:
    > > 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("PROCESSOR_ARCHITECTURE");
    > >
    > > 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?
    > >

    >
    > 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


    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?
    Protoman, Nov 30, 2005
    #4
  5. Protoman wrote:

    > Still, I wonder... Guess I'll just succom to having to think backwards
    > with getenv().


    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().

    > 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?


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

    HTH,
    - J.
    Jacek Dziedzic, Nov 30, 2005
    #5
  6. Protoman

    Greg Guest

    Protoman wrote:
    > 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("PROCESSOR_ARCHITECTURE");


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

    const std::string cpu( getenv("PROCESSOR_ARCHITECTURE"));

    > 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?


    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
    Greg, Nov 30, 2005
    #6
  7. Protoman wrote:
    >
    > 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?


    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
    Karl Heinz Buchegger, Nov 30, 2005
    #7
  8. Protoman

    Guest

    Greg wrote:
    > Protoman wrote:


    > > const char* cpu=getenv("PROCESSOR_ARCHITECTURE");

    >
    > Since this is a C++ group let's declare cpu like this:
    >
    > const std::string cpu( getenv("PROCESSOR_ARCHITECTURE"));


    We really should something like map<string,string> env;' in std,
    so we'd simply say if( std::env["PROCESSOR_ARCHITECTURE"]=="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
    , Nov 30, 2005
    #8
  9. "Protoman" <> wrote in message
    news:...

    > Still, I wonder... Guess I'll just succom to having to think backwards
    > with getenv().


    Nope -- that won't work either.
    Andrew Koenig, Nov 30, 2005
    #9
  10. Protoman

    Protoman Guest

    This is SO confusing
    Protoman, Dec 1, 2005
    #10
  11. Protoman

    Marcus Kwok Guest

    Protoman <> wrote:
    > This is SO confusing


    *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
    Marcus Kwok, Dec 1, 2005
    #11
  12. Protoman

    Ron House Guest

    Protoman wrote:

    > This is SO confusing


    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
    > zero depending on whether the first string is before, the same as, or

    after the second alphabetically.

    therefore

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

    --
    Ron House
    http://www.sci.usq.edu.au/staff/house
    Ethics website: http://www.sci.usq.edu.au/staff/house/goodness
    Ron House, Dec 1, 2005
    #12
  13. Protoman

    Guest

    Marcus Kwok wrote:

    > 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";
    > }


    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.
    , Dec 1, 2005
    #13
  14. Marcus Kwok wrote:
    >
    > Protoman <> wrote:
    > > This is SO confusing

    >
    > *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;
    > }
    >


    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
    Karl Heinz Buchegger, Dec 1, 2005
    #14
  15. "Protoman" <> writes:

    > This is SO confusing


    What is confusing?
    Niklas Norrthon, Dec 1, 2005
    #15
  16. Protoman

    Ben Pope Guest

    *IT* is confusing.

    Ben Pope
    Ben Pope, Dec 1, 2005
    #16
  17. Protoman

    Mike Smith Guest

    Protoman wrote:
    > This is SO confusing


    <sigh> Your problem is not with getenv(). Your problem is that you are
    comparing pointers when you think you are comparing strings.

    char const *a = "Hello!";
    char const *b = "Hello!";
    if (a == b) printf("Equal!");

    In the code fragment above, the printf() will never get called, because
    the values of a and b are different, even though the strings they point
    to are the same.

    char const *a = "Hello!";
    char const *b = "Hello!";
    if (!strcmp(a, b)) printf("Equal!");

    *This* will work because the library function strcmp() compares, not the
    pointer values themselves, but the character strings that the pointers
    point to.

    --
    Mike Smith
    Mike Smith, Dec 1, 2005
    #17
  18. Protoman

    Andre Kostur Guest

    Mike Smith <> wrote in news:11oua9gf1kp8le3
    @news.supernews.com:

    > Protoman wrote:
    >> This is SO confusing

    >
    ><sigh> Your problem is not with getenv(). Your problem is that you are
    > comparing pointers when you think you are comparing strings.
    >
    > char const *a = "Hello!";
    > char const *b = "Hello!";
    > if (a == b) printf("Equal!");
    >
    > In the code fragment above, the printf() will never get called, because
    > the values of a and b are different, even though the strings they point
    > to are the same.


    Actually in this case it might. The compiler may realize that those two
    are the same string literal and only make one copy of it. A better example
    would be:

    char a[] = "Hello!";
    char b[] = "Hello!";

    This would force a and b to be at different memory locations.
    Andre Kostur, Dec 1, 2005
    #18
    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. vertigo

    setuid() and getenv()?

    vertigo, Jul 16, 2004, in forum: Perl
    Replies:
    1
    Views:
    678
    Joe Smith
    Jul 17, 2004
  2. J Krugman
    Replies:
    3
    Views:
    428
    Tor Iver Wilhelmsen
    Aug 5, 2004
  3. lordy

    To getenv or not getenv

    lordy, Jul 28, 2006, in forum: Java
    Replies:
    2
    Views:
    4,769
    lordy
    Jul 28, 2006
  4. Horace Nunley

    why why why does function not work

    Horace Nunley, Sep 27, 2006, in forum: ASP .Net
    Replies:
    1
    Views:
    450
    =?Utf-8?B?UGV0ZXIgQnJvbWJlcmcgW0MjIE1WUF0=?=
    Sep 27, 2006
  5. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,762
    Smokey Grindel
    Dec 2, 2006
Loading...

Share This Page