Thread: Test of Equality for String Macro - Invalid?

  1. #1
    Registered User
    Join Date
    Aug 2008
    Posts
    129

    Test of Equality for String Macro - Invalid?

    I'm trying to understand the problem here, and I've reduced it to a minimal test-case, main.c:
    Code:
    #define FOO "foo"
    
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char** argv) {
    #if FOO == 7
    	/* ... */
    #else
    	/* ... */
    #endif
    	printf("Done\n");
    	return (EXIT_SUCCESS);
    }
    I get this when compiling it:
    Code:
    $ gcc main.c
    main.c:7:5: error: token ""foo"" is not valid in preprocessor expressions
    ??? Am I using an incorrect operator?

    EDIT: Oh, I should also note that "Done" is never printed, even if no errors or warning are encountered. Not sure if that's related...
    Last edited by Jesdisciple; 01-23-2009 at 11:35 PM.

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Just use strcmp or something. The equality operator is not for strings; at least, it doesn't do a lexicographic comparison.

  3. #3
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You're only allowed a constant behind an #if. "foo"==7 is not a constant, as it requires taking the address of the string "foo".

  4. #4
    Registered User
    Join Date
    Aug 2008
    Posts
    129
    I'm surprised the preprocessor doesn't understand more complex comparisons than the compiler... Anyhow, thanks!

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Jesdisciple View Post
    I'm surprised the preprocessor doesn't understand more complex comparisons than the compiler... Anyhow, thanks!
    And exactly what do you expect "foo" to equal, numerically speaking?

    If you want a set of values, you can define a number of constants, and then set your compile-option to one of those constants, e.g.
    Code:
    #define FOO_TYPE 1
    #define BAR_TYPE 2
    #deifne BAZ_TYPE 3
    #define CONFIG_TYPE FOO_TYPE
    ...
    
    #if CONFIG_TYPE == FOO_TYPE
    ...
    #else if CONFIG_TYPE == BAR_TYPE
    ...
    #else if CONFIG_TYPE == BAZ_TYPE
    ...
    #else 
    #error Must define CONFIG_TYPE macro
    #endif
    ...
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Registered User
    Join Date
    Aug 2008
    Posts
    129
    I wouldn't expect a numerical value per se, but several numerical values. Given the expansions the preprocessor is capable of, it seems to me that it could expand a string into a number of characters and compare each character against its corresponding value (which would have been 'f' == 7 && 'o' == 0 && 'o' == 0 in this case).
    Last edited by Jesdisciple; 01-24-2009 at 12:51 PM.

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Jesdisciple View Post
    I wouldn't expect a numerical value per se, but several numerical values. Given the expansions the preprocessor is capable of, it seems to me that it could expand a string into a number of characters and compare each character against its corresponding value (which would have been 'f' == 7 && 0 == 'o' && 0 == 'o' in this case).
    Assuming your logic is somewhat correct, I'd at least expect the values to be:
    'f' == 0x66
    'o' == 0x6f
    'o' == 0x6f
    [Assuming ASCII, but no other character set I know of has 'o' as zero, nor 'f' as 7].

    It is POSSIBLE that the preprocessor would understand 'abc' as a numeric constant, although translating that to a decimal number involves knowing whether is is stored as 'a', 'b', 'c', 0 or 0, 'c', 'b', 'a' [or possibly some other permutation of the possible patterns of 0, a, b and c] and what that corresponds to as a decimal value. Tricky, but perhaps possible.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Registered User
    Join Date
    Aug 2008
    Posts
    129
    I was demonstrating what the comparison would expand to, and I reversed the 0s and 'o's until my edit. I didn't assign any values to the characters, just interpreted a comparison between a string and any other value as an incremental comparison of each set of corresponding components (where a number has only one component which is 0-padded as necessary).

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Right, so if you use single-quotes, you will get something along those lines - I'm not sure if the C preprocessor accepts single-quoted characters. C itself does - and the corresponding value is an integer.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Jesdisciple View Post
    I'm surprised the preprocessor doesn't understand more complex comparisons than the compiler... Anyhow, thanks!
    The preprocessor is pretty dumb. It wasn't designed for complex things such as comparing strings.
    Technically, this should be possible in C++ if you use const and compare the individual elements of the const char array.
    In C++0x, it might even be possible to use a const function to do this at compile time.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User
    Join Date
    Aug 2008
    Posts
    129
    Quote Originally Posted by matsp View Post
    Right, so if you use single-quotes, you will get something along those lines - I'm not sure if the C preprocessor accepts single-quoted characters. C itself does - and the corresponding value is an integer.
    But that would defeat the purpose described in my original post, because the characters would be stored as separate macros.

    In reflection, I realize that the behavior I expected while I was actually typing the code (rather than responding here) was that the preprocessor would actually compare the literal tokens - "foo" (5 characters) and 7 (1 character). I didn't expect it to even be conscious of compiler concepts like types, just literal code.

    And for the record, I actually did use the strcmp() solution before the macro, but I wanted to optimize the executable by processing the equality before compilation rather than at runtime.

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Compile-time optimizations is not C's strong side.
    C++ is much better in this regard.
    I think you've hit a snag.
    But perhaps you can hope the compiler optimizes it away if you tell it that it's constant data.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    The C preprocessor does accept single quoted characters as constants.

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I have a feeling we are missing something important here - I suspect that the REAL code is doing something a bit different from the posted code, and what has been removed is important to understnad for us to be able to provide PROPER guidance of how you go about this using the C preprocessor [assuming it is possible].

    And no, I didn't mean comparing single characters. You CAN have a multicharacter constant like this:
    Code:
    int x = 'foo';
    I still haven't figured out whether those type of constants are available in the preprocessor - I think so. They are, however, clearly defined as "implementation dependant", so how this value is stored (e.g. if it is stored as the bytes 0, 'o', 'o', 'f' or some other way, is entirely up to the compiler, and it may not even be the same for two differnet compilers on the same model of processor [although IT PROBABLY IS]).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  15. #15
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by matsp View Post
    I have a feeling we are missing something important here - I suspect that the REAL code is doing something a bit different from the posted code, and what has been removed is important to understnad for us to be able to provide PROPER guidance of how you go about this using the C preprocessor [assuming it is possible].

    And no, I didn't mean comparing single characters. You CAN have a multicharacter constant like this:
    Code:
    int x = 'foo';
    I still haven't figured out whether those type of constants are available in the preprocessor - I think so. They are, however, clearly defined as "implementation dependant", so how this value is stored (e.g. if it is stored as the bytes 0, 'o', 'o', 'f' or some other way, is entirely up to the compiler, and it may not even be the same for two differnet compilers on the same model of processor [although IT PROBABLY IS]).

    --
    Mats
    Oh indeed. I suppose it's easy to check your particular implementation:
    Code:
    include <stdio.h>
    #define FOO 'foo'
    
    int main() {
        printf("%d\n", 'foo');
        printf("%d\n", FOO);
    
    #if FOO == 0x666f6f
        printf("In order\n");
    #elif FOO == 0x6f6f66
        printf("Backwards\n");
    #else
        printf("Something else\n");
    #endif
        return 0;
    }
    For what it's worth I get "in order" using gcc on the Mac, but I wouldn't extend that very far.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. MSVC Template Constructor/Assignment Errors
    By LuckY in forum Windows Programming
    Replies: 3
    Last Post: 07-22-2005, 02:57 PM
  2. Help w/ complicated variable test
    By Jungle in forum C Programming
    Replies: 4
    Last Post: 03-01-2005, 04:48 PM
  3. Why is my program freezing?
    By ShadowMetis in forum Windows Programming
    Replies: 8
    Last Post: 08-20-2004, 03:20 PM
  4. Question About Linker Errors In Dev-C++
    By ShadowMetis in forum C++ Programming
    Replies: 9
    Last Post: 08-18-2004, 08:42 PM