GCC Standard Predefined Macros

  • The following simplified line of code complied fine on Xcode 2.x in my
    cocoa application.

        char *file = basename(__FILE__)

    Xcode 3.0 complies the code with the following error: warning: passing
    argument 1 of "basename" discards qualifiers from pointer target type.

    __FILE__ is a C string or a pointer to char so why the error message?

    The following Apple link doesn't seem shed any light.

        http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/cpp/Stand
    ard-Predefined-Macros.html


    I have check on the web and can't seem to find any thing relevant.

    Any ideas?

    Regards,
    Richard
  • You are passing a const char* to a function which takes a char*.
    This was never legal C code.
    strcpy __FILE__ into your own string before passing it into basename.
    Also, this is not a Cocoa question.

    Richard Somers wrote:
    > The following simplified line of code complied fine on Xcode 2.x in my
    > cocoa application.
    >
    > char *file = basename(__FILE__)
    >
    > Xcode 3.0 complies the code with the following error: warning: passing
    > argument 1 of "basename" discards qualifiers from pointer target type.
    >
    > __FILE__ is a C string or a pointer to char so why the error message?
    >
    > The following Apple link doesn't seem shed any light.
    >
    >
    > http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/cpp/Stand
    ard-Predefined-Macros.html

    >
    >
    > I have check on the web and can't seem to find any thing relevant.
    >
    > Any ideas?
    >
    > Regards,
    > Richard
  • John,

    Thanks for your help. I will study my C more carefully (again).

    Richard

    On Dec 7, 2007, at 9:52 AM, John Stiles wrote:

    > You are passing a const char* to a function which takes a char*.
    > This was never legal C code.
    > strcpy __FILE__ into your own string before passing it into basename.
    > Also, this is not a Cocoa question.
    >
    > Richard Somers wrote:
    >> The following simplified line of code complied fine on Xcode 2.x in
    >> my cocoa application.
    >>
    >> char *file = basename(__FILE__)
    >>
    >> Xcode 3.0 complies the code with the following error: warning:
    >> passing argument 1 of "basename" discards qualifiers from pointer
    >> target type.
    >>
    >> __FILE__ is a C string or a pointer to char so why the error message?
    >>
    >> The following Apple link doesn't seem shed any light.
    >>
    >> http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/cpp/Stand
    ard-Predefined-Macros.html

    >>
    >> I have check on the web and can't seem to find any thing relevant.
    >>
    >> Any ideas?
    >
  • On Dec 7, 2007, at 11:52 AM, John Stiles wrote:

    > You are passing a const char* to a function which takes a char*.

    This is true.

    > This was never legal C code.

    The statement 'This was never legal C code,' however, is not correct.
    It is perfectly legal C code.  One can reason that if it were not
    legal C code, it would generate an error, not a warning.  From various
    references:

    Section 6.7.3.5 of the current C99 standard (WG14/N1256 ISO/IEC
    9899:TC3):

    "If an attempt is made to modify an object de�ned with a const-
    quali�ed type through use of an lvalue with non-const-quali�ed
    type, the behavior is unde�ned."

    page 187, K&R C Programming Language, 2nd/ANSI ed:

    "A const object may be initialized, but not thereafter assigned
    to. ... The purpose of const is to announce objects that may be placed
    in read-only memory, and perhaps to increase opportunities for
    optimization. ... Except that it should diagnose explicit attempts to
    change const objects, a compiler may ignore these qualifiers."

    See also 'Expert C Programing - Deep C Secrets' by Peter van der
    Linden. This is an excellent book on the more esoteric points of the C
    language. The book offers the following 'Handy Heuristic':

    "The keyword const doesn't turn a variable into a constant! A symbol
    with the const qualifier merely means that the symbol cannot be used
    for assignment. This makes the value read-only through that symbol; it
    does not prevent the value from being modified through some other
    means internal (or even external) to the program. ... As Ken Thompson
    pointed out, "The const keyword only confuses library interfaces with
    the hope of catching some rare errors." In retrospect, the const
    keyword would have been better named readonly."

    A function with a prototype foo(const char *bar) says "bar is a
    pointer to a char type that is read only." The prototype makes it
    explicit that the function will not modify the characters at the
    address pointed to by bar.  Without the const qualifier, the foo()
    function may modify the characters at the address bar, but is in no
    way required to modify them.

    As section 6.7.3.5 says, the behavior is undefined in the case where a
    const qualified type somehow becomes an lvalue, such as in the case of
    the original example:

    int foo(char *bar);

    {
      const char *constp = "read-only";
      foo(constp); // Warning: assignment discards qualifiers from
    pointer target type
                    // This means foo may not honor the expected read-only
    behavior,
                    // but ultimately this is not an error if foo does
    not, in fact,
                    // modify the characters pointed to by constp.
    }

    int foo(char *bar) { bar[0] = 0; /* Undefined when called with constp,
    and no warning or error given. */ }

    compared to:

    int foo(char *bar) { return(bar[0] == 0 ? 0 : 1); /* constp is not
    modified, and the assignment warning does not indicate an actual
    problem. */ }

    However, the following would be an error:

    int foo(const char *bar);

    {
      const char *constp = "read-only";
      foo(constp); // No warning given.
    }

    int foo(const char *bar) { bar[0] = 0; /* Error: assignment of read-
    only location */ }

    Naturally, one can pass types that are not const qualified (read-
    write) to functions where the prototype declares they will be treated
    as const (read-only).

    If one investigates the warning and is assured that basename(char
    *name) (can|does|will) not modify the characters pointed to by the
    argument name (which in practice is more than likely and is almost
    always just a harmless warning, as Ken Thompson eludes to), one can
    suppress the warning message by casting to (char *), such as:

    char *file = basename((char *)__FILE__);

    What's interesting in Richards example though, and the 'simplified'
    part obviously plays a big part in this, is __FILE__ is a pre-
    processor macro which will be re-written as "SOURCE_FILE" when the
    compiler proper finally sees it.  A string literal such as that is not
    const qualified, and is perfectly legal to write to.  This is also the
    reason why the compiler can't coalesce identical string literals in to
    just one entry in the object file by default.

    Then there's the less often seen:

    char *file = basename(char * const name);

    Which qualifies the argument name as const, but not the type pointed
    to be name.  Thus, name[0] = 0 is fine, but name++ is not. The more
    commonly seen const char *name qualifies the type pointed by name is
    const, making name++ legal and name[0] = 0 an error.  And lets not
    forget const char * const name, making it illegal to modify the symbol
    name or what it points to.

    > strcpy __FILE__ into your own string before passing it into basename.

    This would be required iff, after investigating the warning, one
    determines that basename (or any functions that it calls) is in fact
    modifying a const qualified type.  In practice, this is rarely the
    case.  Another potential false warning is when a pointer to a non-
    const qualified type is tainted and 'promoted' in some way to const,
    such as through an assignment to a const qualified symbol, or via a
    function prototype.

    Sorry for the long post.  The usage of 'const' is just one of the
    lesser traveled paths in the C language, and this post is  hopefully
    educational to those who've not had the.. privlige? of getting to know
    'const'.  Peter van der Linden gives several pages to the topic, and
    his Expert C Programming book comes highly recommended.  It covers
    many topics that I haven't seen covered else where, and is a very easy
    and enjoyable read.

    And 'const' is a piece of cake compared to 'restrict', believe it or
    not.  :(
  • On Dec 8, 2007, at 4:58 AM, John Engelhart wrote:

    >> This was never legal C code.
    >
    > The statement 'This was never legal C code,' however, is not
    > correct.  It is perfectly legal C code.  One can reason that if it
    > were not legal C code, it would generate an error, not a warning.

    Sorry. I should have said "this isn't legal C++ code."
    As C, it's unfortunately a legal construct.
  • All,

    I would like thank John Engelhart for his lengthy post on const
    objects in C to help educate us all on this subject.

    I have discovered the root of my specific problem. The "basename"
    function prototype changed with Leopard and Apple's UNIX 03
    certification.

    The function argument was changed from "const char *" to "char *". The
    follow code fragment is found in the libgen.h header.

    #if __DARWIN_UNIX03

    char *basename(char *);

    #else  /* !__DARWIN_UNIX03 */

    char *basename(const char *);

    #endif  /* __DARWIN_UNIX_03 */

    This change is surprising to me. I would have thought that UNIX 03
    would expect more out of a function not less.

    Regards,
    Richard

    On Dec 7, 2007, at 9:49 AM, Richard Somers wrote:

    > The following simplified line of code complied fine on Xcode 2.x in
    > my cocoa application.
    >
    > char *file = basename(__FILE__)
    >
    > Xcode 3.0 complies the code with the following error: warning:
    > passing argument 1 of "basename" discards qualifiers from pointer
    > target type.
previous month december 2007 next month
MTWTFSS
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
Go to today