How does this storage of a string in a multi-dimensional int array work

Discussion in 'C Programming' started by Angus, Mar 8, 2011.

  1. Angus

    Angus Guest

    I was wondering how this worked.

    #include <stdio.h>

    int main(){

    int pos = 1;

    static const int tbl2[6][4] = {
    1000, 1, 10, (int)"abc",
    1001, 2, 11, (int)"defg",
    1100, 3, 12, (int)"hijkl",
    1000, 4, 13, (int)"mnopqr",
    1001, 5, 14, (int)"stuvwxyz",
    1100, 6, 15, (int)"1234567890"
    };

    printf("row=%i, col1=%i, col2=%i, col3=%i, col4=%s\n", pos,
    tbl2[pos][0], tbl2[pos][1], tbl2[pos][2], tbl2[pos][3]);

    return 0;
    }

    This will print:
    row=1, col1=1001, col2=2, col3=11, col4=defg

    I was a little surprised it worked.

    How are the fourth column items stored? I assume that in the array
    the fourth column items are all stored as char pointers and so can be
    stored in an int. Because this is a static I assume there is some
    global section of memory where these items are stored?

    If this array were stored in a program then the executable should grow
    by sizeof(char) * total string length?
     
    Angus, Mar 8, 2011
    #1
    1. Advertising

  2. Angus

    Fred Guest

    Re: How does this storage of a string in a multi-dimensional intarray work

    On Mar 8, 11:09 am, Angus <> wrote:
    > I was wondering how this worked.
    >
    > #include <stdio.h>
    >
    > int main(){
    >
    >    int pos = 1;
    >
    >    static const int tbl2[6][4] = {
    >       1000, 1, 10, (int)"abc",
    >       1001, 2, 11, (int)"defg",
    >       1100, 3, 12, (int)"hijkl",
    >       1000, 4, 13, (int)"mnopqr",
    >       1001, 5, 14, (int)"stuvwxyz",
    >       1100, 6, 15, (int)"1234567890"
    >    };
    >
    >    printf("row=%i, col1=%i, col2=%i, col3=%i, col4=%s\n", pos,
    > tbl2[pos][0], tbl2[pos][1], tbl2[pos][2], tbl2[pos][3]);
    >
    >    return 0;
    >
    > }
    >
    > This will print:
    > row=1, col1=1001, col2=2, col3=11, col4=defg
    >
    > I was a little surprised it worked.
    >
    > How are the fourth column items stored?  I assume that in the array
    > the fourth column items are all stored as char pointers and so can be
    > stored in an int.  


    Doesn't work on my computer, where sizeof(char*) != sizeof(int)

    >Because this is a static I assume there is some
    > global section of memory where these items are stored?
    >
    > If this array were stored in a program then the executable should grow
    > by sizeof(char) * total string length?
     
    Fred, Mar 8, 2011
    #2
    1. Advertising

  3. Angus <> writes:
    > I was wondering how this worked.
    >
    > #include <stdio.h>
    >
    > int main(){
    >
    > int pos = 1;
    >
    > static const int tbl2[6][4] = {
    > 1000, 1, 10, (int)"abc",
    > 1001, 2, 11, (int)"defg",
    > 1100, 3, 12, (int)"hijkl",
    > 1000, 4, 13, (int)"mnopqr",
    > 1001, 5, 14, (int)"stuvwxyz",
    > 1100, 6, 15, (int)"1234567890"
    > };
    >
    > printf("row=%i, col1=%i, col2=%i, col3=%i, col4=%s\n", pos,
    > tbl2[pos][0], tbl2[pos][1], tbl2[pos][2], tbl2[pos][3]);
    >
    > return 0;
    > }
    >
    > This will print:
    > row=1, col1=1001, col2=2, col3=11, col4=defg
    >
    > I was a little surprised it worked.
    >
    > How are the fourth column items stored? I assume that in the array
    > the fourth column items are all stored as char pointers and so can be
    > stored in an int. Because this is a static I assume there is some
    > global section of memory where these items are stored?


    The entire array is stored in some region of memory that persists
    as long as the program is running, because it has what the language
    standard calls "static storage duration". But you could drop the
    "static" (which would cause it to be in storage that goes away when
    the enclosing block terminates) and the "const", and it probably
    wouldn't change the results.

    > If this array were stored in a program then the executable should grow
    > by sizeof(char) * total string length?


    The fact that the int elements are part of an array is irrelevent.
    Here's a simpler program that illustrates the same thing:

    #include <stdio.h>

    int main(void) {
    const int s = (int)"Don't do this"; /* line 4 */
    printf("%s\n", s); /* line 5 */
    return 0;
    }

    When a string literal, or any array expression, is evaluated, it's
    implicitly converted to a pointer to its first element (usually; see
    below [*]).

    On line 4, a pointer to the 'D' in the string is converted from char*
    to int. The result of such a conversion is implementation-defined.
    If pointers are bigger than ints, it's likely to lose information.
    Even if they aren't, the result is likely to be meaningful, but it
    doesn't have to be. (My debugger tells me that, on my system, the
    value happens to be 134513888, which means that the string starts at
    memory address 0x080484e0. Your results are very likely to differ.)

    Typically a pointer-to-integer conversion will just copy the bits of the
    representation, but other behaviors are permitted; the implementation
    just has to document it.

    On line 5, we pass an int value to printf, with a "%s" format, which
    expects a char* argument. This isn't just implementation-defined, it's
    undefined behavior; passing anything other than a char* means you're
    lying to printf, and it can do anything it likes. *If* int arguments
    and char* arguments happen to be passed to variadic functions in the
    same way (which is commonly true), then the bits making up the
    representation of s are likely to be interpreted by printf *as if* they
    were the bits making up the representation of a char* object. Note that
    this isn't a value conversion; the code is interpreting the raw memory
    containing the value of s as if it were a pointer object.

    Now *if* the pointer-to-integer conversion on line 4 just copied the
    bits, then this reinterpretation of the int object as if it were a char*
    is likely to behave as if it really were a char* object pointing to the
    first character of the string literal "Don't do this".

    Note that I wrote "likely", not "certain". One of the many things that
    could go wrong is that char* might have stricter alignment requrements
    than int. Suppose both types are 4 bytes, char* requires 4-byte
    alignment, int only requires 2-byte alignment, and s happens to be
    allocated at an address that's not a multiple of 4 bytes. Then trying
    to read the contents of s as if it were a char*, even though all the
    bits are correct, could behave in arbitrarily bad ways, from crashing
    the program, to quietly ignoring the low-order bits, to whatever else
    you can think of.

    The bottom line is that the program's behavior is undefined. If
    anything goes wrong, it's the fault of the program, not of the
    implementation.

    In this particular case, on my implementation and on yours, the
    undefined behavior gave us the worst result possible: it appeared
    to behave "correctly" -- which just makes it that much harder to
    track down the problem.

    [*] I wrote above that an array expression, whene evaluated,
    is implicitly converted to a pointer to its first element.
    This conversion doesn't happen of the expression is the operand of
    a unary "&" or "sizeof" operator, or if it's a string literal in
    an initializer used to initialize an array object. For example,
    ``sizeof "hello"'' yields 6 (the size of the array object, including
    the terminating '\0'), not sizeof (char*), which is what it would
    yield if the conversion were done.

    --
    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, Mar 8, 2011
    #3
  4. Angus

    Angus Guest

    Re: How does this storage of a string in a multi-dimensional intarray work

    On Mar 8, 7:38 pm, Fred <> wrote:
    > On Mar 8, 11:09 am, Angus <> wrote:
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > > I was wondering how this worked.

    >
    > > #include <stdio.h>

    >
    > > int main(){

    >
    > >    int pos = 1;

    >
    > >    static const int tbl2[6][4] = {
    > >       1000, 1, 10, (int)"abc",
    > >       1001, 2, 11, (int)"defg",
    > >       1100, 3, 12, (int)"hijkl",
    > >       1000, 4, 13, (int)"mnopqr",
    > >       1001, 5, 14, (int)"stuvwxyz",
    > >       1100, 6, 15, (int)"1234567890"
    > >    };

    >
    > >    printf("row=%i, col1=%i, col2=%i, col3=%i, col4=%s\n",pos,
    > > tbl2[pos][0], tbl2[pos][1], tbl2[pos][2], tbl2[pos][3]);

    >
    > >    return 0;

    >
    > > }

    >
    > > This will print:
    > > row=1, col1=1001, col2=2, col3=11, col4=defg

    >
    > > I was a little surprised it worked.

    >
    > > How are the fourth column items stored?  I assume that in the array
    > > the fourth column items are all stored as char pointers and so can be
    > > stored in an int.  

    >
    > Doesn't work on my computer, where sizeof(char*) != sizeof(int)
    >
    >
    >
    >
    >
    >
    >
    > >Because this is a static I assume there is some
    > > global section of memory where these items are stored?

    >
    > > If this array were stored in a program then the executable should grow
    > > by sizeof(char) * total string length?


    Out of interest, what is the platform?
     
    Angus, Mar 8, 2011
    #4
  5. Angus

    Ian Collins Guest

    Re: How does this storage of a string in a multi-dimensional intarray work

    On 03/ 9/11 09:03 AM, Angus wrote:
    > On Mar 8, 7:38 pm, Fred<> wrote:
    >> On Mar 8, 11:09 am, Angus<> wrote:
    >>
    >>> How are the fourth column items stored? I assume that in the array
    >>> the fourth column items are all stored as char pointers and so can be
    >>> stored in an int.

    >>
    >> Doesn't work on my computer, where sizeof(char*) != sizeof(int)


    > Out of interest, what is the platform?


    Most current 64 bit platforms.

    --
    Ian Collins
     
    Ian Collins, Mar 8, 2011
    #5
  6. On Tue, 8 Mar 2011 11:09:58 -0800 (PST)
    Angus <> wrote:
    > I was wondering how this worked.


    By accident.

    > #include <stdio.h>
    >
    > int main(){
    >
    > int pos = 1;
    >
    > static const int tbl2[6][4] = {
    > 1000, 1, 10, (int)"abc",
    > 1001, 2, 11, (int)"defg",
    > 1100, 3, 12, (int)"hijkl",
    > 1000, 4, 13, (int)"mnopqr",
    > 1001, 5, 14, (int)"stuvwxyz",
    > 1100, 6, 15, (int)"1234567890"
    > };
    >
    > printf("row=%i, col1=%i, col2=%i, col3=%i, col4=%s\n", pos,
    > tbl2[pos][0], tbl2[pos][1], tbl2[pos][2], tbl2[pos][3]);
    >
    > return 0;
    > }
    >
    > This will print:
    > row=1, col1=1001, col2=2, col3=11, col4=defg


    Perhaps it will , perhaps it will print something else , perhaps it
    will just crash.

    > I was a little surprised it worked.


    C programming is full of surprises , both pleasant and unpleasant ones.

    > How are the fourth column items stored? I assume that in the array
    > the fourth column items are all stored as char pointers and so can be
    > stored in an int.


    There is no guarantee that a char* can be stored in an int .For your
    code to work as you think it will it is necessary that a char* can be
    stored in an int |and| that when converted back to char* it will compare
    equal to the original pointer. The second part is necessary for the
    printf(...%s...) to work. There's no guarantee that the second part
    will work either.

    > Because this is a static I assume there is some
    > global section of memory where these items are stored?


    What is a "global section of memory" ?

    > If this array were stored in a program then the executable should grow
    > by sizeof(char) * total string length?


    It is always the case that sizeof(char) == 1 .The space to store all
    the stuff in the array and all the stuff in the initialiser would have
    to be at least sizeof(int) * 6 * 4 plus the total length of the strings.
    How much larger the executable will become or indeed if there will be
    an executable depends on the translator which might be an interpreter
    in which case it won't produce an executable.

    --
    Metadiscussion is evil !
     
    Spiros Bousbouras, Mar 8, 2011
    #6
  7. Spiros Bousbouras <> writes:
    [...]
    > There is no guarantee that a char* can be stored in an int .For your
    > code to work as you think it will it is necessary that a char* can be
    > stored in an int |and| that when converted back to char* it will compare
    > equal to the original pointer. The second part is necessary for the
    > printf(...%s...) to work. There's no guarantee that the second part
    > will work either.

    [...]

    There is no conversion back to char*. Given certain assumptions, printf
    will interpret the contents of the int object as if it were a char*
    object. This may well have the same effect as a value conversion, but
    it might not.

    --
    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, Mar 8, 2011
    #7
    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. Venkat
    Replies:
    4
    Views:
    994
    Venkat
    Dec 5, 2003
  2. Schnoffos
    Replies:
    2
    Views:
    1,237
    Martien Verbruggen
    Jun 27, 2003
  3. Hal Styli
    Replies:
    14
    Views:
    1,686
    Old Wolf
    Jan 20, 2004
  4. Vineet Jain
    Replies:
    9
    Views:
    456
    Fredrik Lundh
    Apr 16, 2004
  5. Wirianto Djunaidi
    Replies:
    2
    Views:
    217
    Wirianto Djunaidi
    Apr 29, 2008
Loading...

Share This Page