String Literals

Discussion in 'C Programming' started by thedude, Jul 22, 2010.

  1. thedude

    thedude Guest

    If I used this return statement in a c function

    return (int)* "hello world";

    From what I know the calling function will only retrieve the character
    'h', right ?

    Is it right to assume that nevertheless, read only memory was
    allocated for the entire string "hello world" , And if so can that
    memory(Or the rest of the characters) be accessed somehow ?

    Thanks in advance.
     
    thedude, Jul 22, 2010
    #1
    1. Advertising

  2. thedude <> wrote:
    > If I used this return statement in a c function


    > return (int)* "hello world";


    Why would you do that?

    > From what I know the calling function will only retrieve the character
    > 'h', right ?


    The caller will receive the address of the string literal
    cast to an int pointer. What that should be good for is
    beyond me since the correct type of the address is const
    char pointer. This conversion to int pointer invokes un-
    defined behaviour. The standard allows to convert an ob-
    ject pointer (e.g. an int *) to a void (or, for historical
    reasons, char) pointer and then the back-conversion of this
    result, but not from every object pointer type to each other
    object pointer type (on some architectures different types
    of pointers may have e.g. different sizes).

    If you dereference the int pointer you got back from the func-
    tion you may get a bus error since an int may have more strict
    alignment requirements than a char, so the string may start at
    an address that's not suitable aligned for accesses via an int
    pointer (even if the cast from const char * to int * didn't
    mess up the address).

    > Is it right to assume that nevertheless, read only memory was
    > allocated for the entire string "hello world"


    Yes, with and without the "nevertheless";-)

    > And if so can that
    > memory(Or the rest of the characters) be accessed somehow ?


    Yes and no. If your machine actually doesn't do anything
    bad when converting from const char * to int * then you may
    be able to convert the returned pointer back to const char *;
    so you can get at the string. But why rely on that? If your
    function is supposed to return a generic pointer you should
    use a void pointer.
    Regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
     
    Jens Thoms Toerring, Jul 22, 2010
    #2
    1. Advertising

  3. thedude

    Sebastian Guest

    On 22 Jul., 15:47, thedude wrote:
    > If I used this return statement in a c function
    >
    > return (int)* "hello world";
    >
    > From what I know the calling function will only retrieve the
    > character 'h', right ?


    Please provide a code snippet that actually compiles or at least is
    supposed to compile. I'm guessing you meant something like this:

    char* foo() {
    return "hello world";
    }

    In this case the function returns a pointer that points to the
    character 'h', yes. But all the characters are placed consecutivly in
    memory.

    > Is it right to assume that nevertheless, read only memory was
    > allocated for the entire string "hello world" ,


    Yes. At least you are not allowed to change any of it. Prefer to use
    the type "const char*" in such cases. This makes any mutation attemp a
    compile-time error.

    int main(void) {
    const char *p = "hello";
    p[0] = 'H'; // compile-time error
    return 0;
    }

    whereas without "const" this program would probably compile on all
    compilers but invoke undefined behaviour.

    > And if so can that memory(Or the rest of the characters) be
    > accessed somehow ?


    Sure. A string literal is a character array with static storage. As
    such, all the characters are stored linearly in memory.

    #include <stdio.h>

    int main(void) {
    const char *p = "hello";
    while (*p) printf("%c",*p++);
    puts("\n");
    return 0;
    }

    This program iterates through the whole string by incrementing the
    pointer until the null terminator is reached. You see, the string
    literal "hello" is an array of 6 characters: 'h', 'e', 'l', 'l', 'o',
    '\0'.

    Cheers
    SG
     
    Sebastian, Jul 22, 2010
    #3
  4. thedude

    Tim Rentsch Guest

    (Jens Thoms Toerring) writes:

    > thedude <> wrote:
    >> If I used this return statement in a c function

    >
    >> return (int)* "hello world";

    >
    > Why would you do that?
    >
    >> From what I know the calling function will only retrieve the character
    >> 'h', right ?

    >
    > The caller will receive the address of the string literal
    > cast to an int pointer. [snip]


    You may want to look again. The cast is to (int),
    not to (int*).
     
    Tim Rentsch, Jul 22, 2010
    #4
  5. Tim Rentsch <> wrote:
    > (Jens Thoms Toerring) writes:


    > > thedude <> wrote:
    > >> If I used this return statement in a c function

    > >
    > >> return (int)* "hello world";

    > >
    > > Why would you do that?
    > >
    > >> From what I know the calling function will only retrieve the character
    > >> 'h', right ?

    > >
    > > The caller will receive the address of the string literal
    > > cast to an int pointer. [snip]


    > You may want to look again. The cast is to (int),
    > not to (int*).


    Ooops, where are my glasses when I need them? Thanks...

    Regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
     
    Jens Thoms Toerring, Jul 22, 2010
    #5
  6. thedude

    Tim Rentsch Guest

    thedude <> writes:

    > If I used this return statement in a c function
    >
    > return (int)* "hello world";
    >
    > From what I know the calling function will only retrieve the character
    > 'h', right ?


    Only the first character of the string literal will
    be accessed, if that's what you mean.

    > Is it right to assume that nevertheless, read only memory was
    > allocated for the entire string "hello world" ,


    It may be but it doesn't have to be. An implementation
    may (legally) compile this the same as it would compile

    return (int) 'h';

    > And if so can that
    > memory(Or the rest of the characters) be accessed somehow ?


    Memory for the string literal need not exist in the
    actual compiled program.
     
    Tim Rentsch, Jul 22, 2010
    #6
  7. thedude

    Tim Rentsch Guest

    Sebastian <> writes:

    > On 22 Jul., 15:47, thedude wrote:
    >> If I used this return statement in a c function
    >>
    >> return (int)* "hello world";
    >>
    >> From what I know the calling function will only retrieve the
    >> character 'h', right ?

    >
    > Please provide a code snippet that actually compiles or at least is
    > supposed to compile. [snip]


    I'm guessing you misread the example line. That's '(int)*',
    not '(int*)'.
     
    Tim Rentsch, Jul 22, 2010
    #7
  8. thedude

    Sebastian Guest

    On 22 Jul., 16:14, Sebastian wrote:
    > On 22 Jul., 15:47, thedude wrote:
    >
    > > If I used this return statement in a c function

    >
    > >   return (int)* "hello world";

    >
    > > From what I know the calling function will only retrieve the
    > > character 'h', right ?

    >
    > Please provide a code snippet that actually compiles or at least is
    > supposed to compile. I'm guessing you meant something like this:
    >
    >   char* foo() {
    >     return "hello world";
    >   }


    Oops.

    return (int)* "hello world"

    is actually legal for a function that returns int. I was assuming you
    made a typo and meant (int*). But it also makes little sense. *"hello
    world" is pretty much equivalent to 'h'. In that case the function
    returns only an integer representing the 'h' character and you won't
    be able to retrieve anything else because the address is lost.

    You should have posted the whole function's body.

    > Cheers
    > SG
     
    Sebastian, Jul 22, 2010
    #8
  9. thedude

    thedude Guest

    Thanks for your response Tim R.(and everyone else)

    Yes I did mean dereference the string literal and cast it to an int.

    Problem is, That function is in an "obnoxious" header file(API) I am
    supposed to use(ie not in my control).
    And I saw that only the first character was being returned, And why
    they did that was beyond me too.

    Ravi

    On Jul 22, 10:27 am, Tim Rentsch <> wrote:
    > Sebastian <> writes:
    > > On 22 Jul., 15:47, thedude wrote:
    > >> If I used this return statement in a c function

    >
    > >>   return (int)* "hello world";

    >
    > >> From what I know the calling function will only retrieve the
    > >> character 'h', right ?

    >
    > > Please provide a code snippet that actually compiles or at least is
    > > supposed to compile. [snip]

    >
    > I'm guessing you misread the example line.  That's '(int)*',
    > not '(int*)'.
     
    thedude, Jul 22, 2010
    #9
  10. On Jul 22, 5:42 pm, thedude <> wrote:
    > Thanks for your response Tim R.(and everyone else)
    >
    > Yes I did mean dereference the string literal and cast it to an int.
    >
    > Problem is, That function is in an "obnoxious" header file(API) I am
    > supposed to use(ie not in my control).
    > And I saw that only the first character was being returned, And why
    > they did that was beyond me too.
    >

    It seems odd.
    However it's quite common to pass chars around as ints. For some
    reason the character 'h' must have been required, and the reason it
    was 'h' and not some other value was that 'h' is the initial character
    of the string "hello world". That would make sense - if the crucial
    string turns to "goodbye cruel world" at some later date the source of
    the 'h' is documented for the maintainer.
     
    Malcolm McLean, Jul 22, 2010
    #10
  11. On 22/07/10 14:47, thedude wrote:

    > return (int)* "hello world";
    >
    > From what I know the calling function will only retrieve the character
    > 'h', right ?
    >
    > Is it right to assume that nevertheless, read only memory was
    > allocated for the entire string "hello world" , And if so can that
    > memory(Or the rest of the characters) be accessed somehow ?


    Why not write the code, compile it and try it? Of course, the answer
    that you get might only apply to your compiler, but then that's often
    the case when people step outside the boundaries of sensible code and
    into the realm of doing bloody stupid things to see what happens.

    Rgds

    Denis McMahon
     
    Denis McMahon, Jul 23, 2010
    #11
  12. On 23/07/10 00:47, Denis McMahon wrote:
    > On 22/07/10 14:47, thedude wrote:
    >
    >> return (int)* "hello world";
    >>
    >> From what I know the calling function will only retrieve the character
    >> 'h', right ?
    >>
    >> Is it right to assume that nevertheless, read only memory was
    >> allocated for the entire string "hello world" , And if so can that
    >> memory(Or the rest of the characters) be accessed somehow ?

    >
    > Why not write the code, compile it and try it? Of course, the answer
    > that you get might only apply to your compiler, but then that's often
    > the case when people step outside the boundaries of sensible code and
    > into the realm of doing bloody stupid things to see what happens.


    Following up, and having tested, there's no way to see the remainder of
    the string literal from the calling function:

    #include <stdio.h>

    int f() {
    return (int)* "hello world";
    }

    int main () {
    int i;
    i = f();
    printf ("%c %i\n",(char)i,i);
    }

    I get:

    h 104

    The calling procedure allocates storage for an int, and receives that
    int. Any pointer to the string literal only exists within the function f
    and is not visible to the calling procedure.

    The address of the integer i in the calling procedure is defined by the
    calling procedure, so even if it is dereferenced to a pointer and cast
    to char, it's not going to contain anything other than (int)'h'.
    #include <stdio.h>

    int f() {
    return (int)* "hello world";
    }

    int main () {
    int i;
    char *c;
    int j;

    i = f();
    c = (char *) &i;
    printf ("%c %d\n",(char)i,i);
    printf ("%s\n---\n",c);

    for (j = 0; j < 12; j++) {
    printf ("%c %d\n",(char)c[j],c[j]);
    }
    }

    I get:

    h 104
    h
    ---
    h 104
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0

    Your mileage may vary.

    Rgds

    Denis McMahon
     
    Denis McMahon, Jul 23, 2010
    #12
  13. thedude <> writes:
    > If I used this return statement in a c function
    >
    > return (int)* "hello world";
    >
    > From what I know the calling function will only retrieve the character
    > 'h', right ?


    Right. Incidentally, the cast is unnecessary; whatever type the
    enclosing function returns, the result of *"hello world" (which is
    of type char) will be implicitly converted to the required type.
    Or if the return type isn't numeric, the cast won't help. But I'm
    guessing that the function returns int.

    I can't think of any reason to write the above rather than just

    return 'h';

    unless perhaps the "hello world" is the result of a macro expansion.

    > Is it right to assume that nevertheless, read only memory was
    > allocated for the entire string "hello world" , And if so can that
    > memory(Or the rest of the characters) be accessed somehow ?


    In the abstract machine, the string literal implies the creation
    of a static object of type "array of char". (It's not necessarily
    read-only; attempting to modify it invokes undefined behavior.)

    But in this case, the only thing the program does with that array is
    retrieve the value of its first element, the 'h'. You *could* have
    accessed the rest of the array, but you didn't. Because of that,
    the compiler is free to eliminate the rest of the array, generating
    code equivalent to "return 'h';". The function returns (a copy of)
    the *value* 'h', not the address where it's stored, so there's no
    way for a caller to use the result to get at the "ello world".

    --
    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, Jul 23, 2010
    #13
  14. thedude

    thedude Guest

    To follow up ...

    I turned out to be a in a bug in the header file that I need to deal
    with for now.
    The intention was to return the first four bytes of the string cast as
    an int.

    So what was intended should have been written as

    return *(int *) "hello world"

    Regarding me writing up the code. Yes, I did have a few shots at it,
    But was not successful(seg. faults) - And that's when I wondered if
    there was a way to do it. Phew, Accusations galore :)

    Ravi


    On Jul 22, 8:47 pm, Keith Thompson <> wrote:
    > thedude <> writes:
    > > If I used this return statement in a c function

    >
    > > return (int)* "hello world";

    >
    > > From what I know the calling function will only retrieve the character
    > > 'h', right ?

    >
    > Right.  Incidentally, the cast is unnecessary; whatever type the
    > enclosing function returns, the result of *"hello world" (which is
    > of type char) will be implicitly converted to the required type.
    > Or if the return type isn't numeric, the cast won't help.  But I'm
    > guessing that the function returns int.
    >
    > I can't think of any reason to write the above rather than just
    >
    >     return 'h';
    >
    > unless perhaps the "hello world" is the result of a macro expansion.
    >
    > > Is it right to assume that nevertheless, read only memory was
    > > allocated for the entire string "hello world" , And if so can that
    > > memory(Or the rest of the characters) be accessed somehow ?

    >
    > In the abstract machine, the string literal implies the creation
    > of a static object of type "array of char".  (It's not necessarily
    > read-only; attempting to modify it invokes undefined behavior.)
    >
    > But in this case, the only thing the program does with that array is
    > retrieve the value of its first element, the 'h'.  You *could* have
    > accessed the rest of the array, but you didn't.  Because of that,
    > the compiler is free to eliminate the rest of the array, generating
    > code equivalent to "return 'h';".  The function returns (a copy of)
    > the *value* 'h', not the address where it's stored, so there's no
    > way for a caller to use the result to get at the "ello world".
    >
    > --
    > 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"
     
    thedude, Jul 23, 2010
    #14
    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. Harri Pesonen

    String literals in Java

    Harri Pesonen, May 28, 2004, in forum: Java
    Replies:
    59
    Views:
    15,123
    Jim Cochrane
    Jun 2, 2004
  2. Pete Elmgreen

    character literals and string

    Pete Elmgreen, Nov 24, 2004, in forum: Java
    Replies:
    3
    Views:
    4,748
  3. Purush
    Replies:
    4
    Views:
    1,760
    Purush Rudrakshala
    Apr 13, 2005
  4. Replies:
    4
    Views:
    901
    Roedy Green
    Nov 21, 2005
  5. John Goche
    Replies:
    8
    Views:
    16,571
Loading...

Share This Page