warning: return makes integer from pointer without a cast

Discussion in 'C Programming' started by Ton 't Lam, Nov 24, 2008.

  1. Ton 't Lam

    Ton 't Lam Guest

    Please, consider the following minimal example code:

    # more f.l
    %option noyywrap

    %{
    #include <string.h>
    %}

    %%

    [0-9]+ return( strdup (yytext));

    %%

    # more main.c
    #include <stdio.h>

    main()
    {
    printf( "%s\n", yylex());
    }

    # flex f.l
    # cc -o prog main.c lex.yy.c
    f.l: In function ‘yylex’:
    f.l:9: warning: return makes integer from pointer without a cast

    The program 'main' works correctly.

    gcc version 4.1.2 20070925 (Red Hat 4.1.2-33)
    flex 2.5.33

    If I cast with (char *) on several places, I see no improvement.
    Googling didn't lead me to a solution either.

    How can I corect the code, so I don't have this warning?

    Many thanks,
    Ton
    Ton 't Lam, Nov 24, 2008
    #1
    1. Advertising

  2. Ton 't Lam <> writes:

    > Please, consider the following minimal example code:
    >
    > # more f.l
    > %option noyywrap
    >
    > %{
    > #include <string.h>
    > %}
    >
    > %%
    >
    > [0-9]+ return( strdup (yytext));
    >
    > %%
    >
    > # more main.c
    > #include <stdio.h>
    >
    > main()
    > {
    > printf( "%s\n", yylex());
    > }
    >
    > # flex f.l
    > # cc -o prog main.c lex.yy.c
    > f.l: In function ‘yylex’:
    > f.l:9: warning: return makes integer from pointer without a cast
    >
    > The program 'main' works correctly.
    >
    > gcc version 4.1.2 20070925 (Red Hat 4.1.2-33)
    > flex 2.5.33
    >
    > If I cast with (char *) on several places, I see no improvement.
    > Googling didn't lead me to a solution either.
    >
    > How can I corect the code, so I don't have this warning?


    This is not a question about C, but about flex. The yylex function it
    generates is declared by default as returning int, but your return
    statement (which gets inserted into yylex) returns a char *. Read
    Chaper 9 of the flex manual ("The Generated Scanner") which explains how
    change the return type. Further questions should go to a forum that
    deals with flex specifically.
    Nate Eldredge, Nov 24, 2008
    #2
    1. Advertising

  3. Ton 't Lam

    Ton 't Lam Guest

    You're right. This is not a question about C, but about flex.

    Anyway, the solution is to have:

    %option noyywrap

    %{
    #include <string.h>
    #define YY_PROTO(proto) proto
    #define YY_DECL char *yylex YY_PROTO(( void ))
    %}

    %%

    [0-9]+ return( (char *) strdup (yytext));

    %%
    Ton 't Lam, Nov 25, 2008
    #3
  4. Ton 't Lam <> writes:
    > You're right. This is not a question about C, but about flex.
    >
    > Anyway, the solution is to have:
    >
    > %option noyywrap
    >
    > %{
    > #include <string.h>
    > #define YY_PROTO(proto) proto
    > #define YY_DECL char *yylex YY_PROTO(( void ))
    > %}
    >
    > %%
    >
    > [0-9]+ return( (char *) strdup (yytext));
    >
    > %%


    Since you didn't post any context from previous articles, it's
    difficult to tell what you changed. Lookup upthread, you originally had:
    [0-9]+ return( strdup (yytext));
    which you've now changed to
    [0-9]+ return( (char *) strdup (yytext));

    That silences the warning, but the warning wasn't the problem. Adding
    a cast to silence a warning is almost never a good idea. Without
    seeing the full C code that's generated from your flex input, it's
    difficult to tell, but here's what I think is happening:

    strdup returns a result of type char*. Your compiler isn't seeing a
    declaration for strdup, so it assumes that it returns int. This alone
    invokes undefined behavior. You were lucky enough to get a warning
    because you tried to use the result in a context that requires a char*
    value (the return statement).

    After you added the cast, the compiler is *still* assuming,
    incorrectly, that strdup returns a result of type int. When the call
    is executed at run time, likely results are that the actual char*
    value returned by the function is treated as an int, or an int value
    is grabbed from some arbitrary location, giving you a garbage int
    value. The cast does two things: it converts this garbage int value
    to char*, and it silences the warning because you've told the compiler
    that you know what you're doing (sorry, but you don't).

    strdup is not a standard function. (It's very commonly provided, but
    the ANSI committee chose not to standardize it back in 1989.) Even if
    your implementation provides strdup, it probably doesn't provide a
    declaration of it in <string.h> unless you do something special to
    enable it.

    The quick solution would be to find out how to enable the declaration
    of strdup in your C implementation. A more portable solution would be
    to write your own strdup implementation (it's not difficult) and give
    it a different name, such as dupstr.

    Either way, lose the cast.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 25, 2008
    #4
  5. Eric Sosman <> writes:
    > Keith Thompson wrote:

    [...]
    >> Since you didn't post any context from previous articles, it's
    >> difficult to tell what you changed. Lookup upthread, you originally had:
    >> [0-9]+ return( strdup (yytext));
    >> which you've now changed to
    >> [0-9]+ return( (char *) strdup (yytext));
    >> That silences the warning, but the warning wasn't the problem.
    >> Adding
    >> a cast to silence a warning is almost never a good idea. Without
    >> seeing the full C code that's generated from your flex input, it's
    >> difficult to tell, but here's what I think is happening:
    >> strdup returns a result of type char*. Your compiler isn't seeing a
    >> declaration for strdup, so it assumes that it returns int. This alone
    >> invokes undefined behavior. You were lucky enough to get a warning
    >> because you tried to use the result in a context that requires a char*
    >> value (the return statement).

    >
    > If so, the diagnostic was extremely misleading. Note the sense
    > of the conversion it complained about: not integer to pointer, but
    > pointer to integer. If the diagnostic is to be believed, then the
    > compiler knew [1] that strdup() returns a pointer, and [2] that the
    > pointer was being converted to an integer in `return'.


    D'oh! You're right.

    > As you say, adding a cast to silence a warning is seldom a good
    > idea, and in this case I suspect it had nothing to do with the cure.
    > The cure was probably the introduction of the YY_PROTO and YY_DECL
    > macros, which most likely changed the return type of the generated
    > C function from `int' to `char*'. If I'm right, then the cast in
    > the `return' statement is harmless, but useless.


    Agreed.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 25, 2008
    #5
  6. Ton 't Lam

    Ton 't Lam Guest

    Keith Thompson wrote:
    > Eric Sosman <> writes:
    >> Keith Thompson wrote:

    > [...]
    >>> Since you didn't post any context from previous articles, it's
    >>> difficult to tell what you changed. Lookup upthread, you originally had:
    >>> [0-9]+ return( strdup (yytext));
    >>> which you've now changed to
    >>> [0-9]+ return( (char *) strdup (yytext));
    >>> That silences the warning, but the warning wasn't the problem.
    >>> Adding
    >>> a cast to silence a warning is almost never a good idea. Without
    >>> seeing the full C code that's generated from your flex input, it's
    >>> difficult to tell, but here's what I think is happening:
    >>> strdup returns a result of type char*. Your compiler isn't seeing a
    >>> declaration for strdup, so it assumes that it returns int. This alone
    >>> invokes undefined behavior. You were lucky enough to get a warning
    >>> because you tried to use the result in a context that requires a char*
    >>> value (the return statement).

    >> If so, the diagnostic was extremely misleading. Note the sense
    >> of the conversion it complained about: not integer to pointer, but
    >> pointer to integer. If the diagnostic is to be believed, then the
    >> compiler knew [1] that strdup() returns a pointer, and [2] that the
    >> pointer was being converted to an integer in `return'.

    >
    > D'oh! You're right.
    >
    >> As you say, adding a cast to silence a warning is seldom a good
    >> idea, and in this case I suspect it had nothing to do with the cure.
    >> The cure was probably the introduction of the YY_PROTO and YY_DECL
    >> macros, which most likely changed the return type of the generated
    >> C function from `int' to `char*'. If I'm right, then the cast in
    >> the `return' statement is harmless, but useless.

    >
    > Agreed.
    >



    Yes, this seems to misleading indeed. It took me quite some re-reading
    to comprehend this error, which is correct anyway.

    It is the return() in flex that returns an integer by default, however
    in this case it ought to be a pointer to character. So you have to declare

    #define YY_PROTO(proto) proto
    #define YY_DECL char *yylex YY_PROTO(( void ))

    From here the return() in flex will return a pointer to a character.

    At first I thought it was the strdup as well, but this is another story.
    I've seen that if you don't strdup the yytext, then on a next invokation
    of yylex() you may get weird results, because yytext (a pointer)
    changes! You simply have to run of a copy, and always save.

    The #include <string.h> contains the declaration of strdup().

    My code now compiles warning free.

    Many thanks for all replies.

    Ton 't Lam
    Ton 't Lam, Nov 26, 2008
    #6
    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. Rocke Robertson
    Replies:
    14
    Views:
    12,974
    Dan Pop
    Oct 2, 2003
  2. Markus Dehmann
    Replies:
    14
    Views:
    920
    Irrwahn Grausewitz
    Jun 28, 2004
  3. Dawn Minnis
    Replies:
    4
    Views:
    1,531
    Dawn Minnis
    Feb 20, 2005
  4. Replies:
    2
    Views:
    1,225
    Martin Ambuhl
    Apr 1, 2005
  5. Juggernaut
    Replies:
    10
    Views:
    1,590
    CBFalconer
    Apr 9, 2005
Loading...

Share This Page