Re: A portable stack in C

Discussion in 'C Programming' started by Barry Schwarz, Nov 15, 2011.

  1. On Mon, 14 Nov 2011 17:54:32 +0100, "io_x" <> wrote:

    >in the while the train go always more far from home
    >i think to these questions:
    >is it possible to build a portable stack in C using uns32_t?


    Since uns32_t is not a portable type, the answer is no. If you could
    be bothered to use uint32_t at least it would comply with n1256. But
    since the type is optional, the answer would still be at best a
    limited yes.

    >is it possible to define in C a pointer of size 32 bits portable
    >as uns32_t? could it be "uns32_t"?


    You have no control over the size of pointers.

    >is it possible using that stack for call of function as
    >f(a, b) <=> push32 b|push32 a| call32 f


    Not on my system which doesn't use a stack or have a push instruction.

    >i remember someone says that for calling function
    >it has to be a stack: i'm agree with him


    You shouldn't believe everything you read on Usenet.

    --
    Remove del for email
    Barry Schwarz, Nov 15, 2011
    #1
    1. Advertising

  2. Barry Schwarz

    jacob navia Guest

    Le 15/11/11 05:55, Barry Schwarz a écrit :
    > On Mon, 14 Nov 2011 17:54:32 +0100, "io_x"<> wrote:
    >
    >> in the while the train go always more far from home
    >> i think to these questions:
    >> is it possible to build a portable stack in C using uns32_t?

    >
    > Since uns32_t is not a portable type, the answer is no. If you could
    > be bothered to use uint32_t at least it would comply with n1256. But
    > since the type is optional, the answer would still be at best a
    > limited yes.
    >
    >> is it possible to define in C a pointer of size 32 bits portable
    >> as uns32_t? could it be "uns32_t"?

    >
    > You have no control over the size of pointers.
    >


    Of course you can. Here is an 8 bit pointer:

    char table[255];
    char pointerInTable;

    Now, "pointerInTable" points to any position within that table. For
    instance to get the contents of position 154:

    pointerInTable = 154;
    val = table[pointerInTable];

    Using this (in plain C) you can have pointers of any size.

    Want a 10 bit pointer?

    Easy.

    char table[1024];
    int pointerInTable; /* Values from 0 to 1023 */

    >> is it possible using that stack for call of function as
    >> f(a, b)<=> push32 b|push32 a| call32 f

    >
    > Not on my system which doesn't use a stack or have a push instruction.
    >


    Ahh OK;

    > You shouldn't believe everything you read on Usenet.
    >


    You are right. I don't believe you that there isn't (by convention)
    a register pointing to the stack, and that

    sub stack,8
    move value,[stack]

    doesn't work.

    Which system are you using?
    jacob navia, Nov 15, 2011
    #2
    1. Advertising

  3. Barry Schwarz

    Ike Naar Guest

    On 2011-11-15, jacob navia <> wrote:
    > Of course you can. Here is an 8 bit pointer:
    >
    > char table[255];
    > char pointerInTable;
    >
    > Now, "pointerInTable" points to any position within that table. For
    > instance to get the contents of position 154:
    >
    > pointerInTable = 154;
    > val = table[pointerInTable];


    This would not work on an implementation where
    char is signed and CHAR_MAX is less than 255.

    An example of such an implementation (the machine I'm currently
    using) has amd64 hardware running NetBSD 5.1.0 with a GCC 4.1.3
    compiler. CHAR_MIN = -128 and CHAR_MAX = 127 .

    "unsigned char pointerInTable;" would probably be more portable.
    Ike Naar, Nov 15, 2011
    #3
  4. Barry Schwarz

    BartC Guest

    "jacob navia" <> wrote in message
    news:j9t7gd$45e$...
    > Le 15/11/11 05:55, Barry Schwarz a écrit :


    >> You have no control over the size of pointers.


    > Of course you can. Here is an 8 bit pointer:
    >
    > char table[255];
    > char pointerInTable;
    >
    > Now, "pointerInTable" points to any position within that table. For
    > instance to get the contents of position 154:
    >
    > pointerInTable = 154;
    > val = table[pointerInTable];


    That's not a pointer as understood in C. It's an array index. Try passing
    pointerInTable to a function, and see if the function can access the table!

    > Using this (in plain C) you can have pointers of any size.
    >
    > Want a 10 bit pointer?
    >
    > Easy.
    >
    > char table[1024];
    > int pointerInTable; /* Values from 0 to 1023 */


    And that one's not even ten bits. It's more likely 32 bits.

    >> You shouldn't believe everything you read on Usenet.

    >
    > You are right. I don't believe you that there isn't (by convention)
    > a register pointing to the stack, and that
    >
    > sub stack,8
    > move value,[stack]
    >
    > doesn't work.
    >
    > Which system are you using?


    Clearly one without a stack, perhaps some lowly controller chip.

    --
    Bartc
    BartC, Nov 15, 2011
    #4
  5. Barry Schwarz

    jacob navia Guest

    Le 15/11/11 11:05, BartC a écrit :
    > "jacob navia" <> wrote in message
    > news:j9t7gd$45e$...
    >> Le 15/11/11 05:55, Barry Schwarz a écrit :

    >
    >>> You have no control over the size of pointers.

    >
    >> Of course you can. Here is an 8 bit pointer:
    >>
    >> char table[255];
    >> char pointerInTable;
    >>
    >> Now, "pointerInTable" points to any position within that table. For
    >> instance to get the contents of position 154:
    >>
    >> pointerInTable = 154;
    >> val = table[pointerInTable];

    >
    > That's not a pointer as understood in C. It's an array index. Try
    > passing pointerInTable to a function, and see if the function can access
    > the table!



    of course it can

    typedef unsigned Pointer;

    int MyFn(Pointer p)
    {
    return table[p];
    }

    Conceptually ANY pointer is an index in a big array called "memory" (or
    RAM if you like).

    This huge array of characters can be accessed in some machines as a
    discontinuous array, composed of several chunks (segments).

    An index into those arrays is composed of two numbers: the chunk
    index and the index within that chunk (segment:eek:ffset)

    >
    >> Using this (in plain C) you can have pointers of any size.
    >>
    >> Want a 10 bit pointer?
    >>
    >> Easy.
    >>
    >> char table[1024];
    >> int pointerInTable; /* Values from 0 to 1023 */

    >
    > And that one's not even ten bits. It's more likely 32 bits.
    >


    Well, all my pointers in my machine are 35 bits (I have only 12GB of
    memory) but they use 64... (Ignoring Virtual Memory)



    >>> You shouldn't believe everything you read on Usenet.

    >>
    >> You are right. I don't believe you that there isn't (by convention)
    >> a register pointing to the stack, and that
    >>
    >> sub stack,8
    >> move value,[stack]
    >>
    >> doesn't work.
    >>
    >> Which system are you using?

    >
    > Clearly one without a stack, perhaps some lowly controller chip.
    >


    Impossible. There isn't a CALL instruction then. It is impossible
    to implement a CALL without a conceptual stack. Yes, you can "push"
    your return address into some register but this is conceptually a stack!
    jacob navia, Nov 15, 2011
    #5
  6. Barry Schwarz

    jacob navia Guest

    Le 15/11/11 10:00, Ike Naar a écrit :
    > On 2011-11-15, jacob navia<> wrote:
    >> Of course you can. Here is an 8 bit pointer:
    >>
    >> char table[255];
    >> char pointerInTable;
    >>
    >> Now, "pointerInTable" points to any position within that table. For
    >> instance to get the contents of position 154:
    >>
    >> pointerInTable = 154;
    >> val = table[pointerInTable];

    >
    > This would not work on an implementation where
    > char is signed and CHAR_MAX is less than 255.
    >
    > An example of such an implementation (the machine I'm currently
    > using) has amd64 hardware running NetBSD 5.1.0 with a GCC 4.1.3
    > compiler. CHAR_MIN = -128 and CHAR_MAX = 127 .
    >
    > "unsigned char pointerInTable;" would probably be more portable.


    Sure, I apologize for that blunder. It is unsigned char of course.
    jacob navia, Nov 15, 2011
    #6
  7. Barry Schwarz

    BartC Guest

    "jacob navia" <> wrote in message
    news:j9temn$o6u$...
    > Le 15/11/11 11:05, BartC a écrit :
    >> "jacob navia" <> wrote in message


    >>> pointerInTable = 154;
    >>> val = table[pointerInTable];

    >>
    >> That's not a pointer as understood in C. It's an array index. Try
    >> passing pointerInTable to a function, and see if the function can access
    >> the table!


    > of course it can
    >
    > typedef unsigned Pointer;
    >
    > int MyFn(Pointer p)
    > {
    > return table[p];
    > }


    So:

    (1) 'table' has to have global scope
    (2) MyFn() can only access one array

    To be able to access any array, you need to pass a second parameter which
    specifies (or 'points to') the array you want, plus the index. Or...

    > Conceptually ANY pointer is an index in a big array called "memory" (or
    > RAM if you like).


    .... forget about normal named arrays in C, and work with a single block of
    memory. So losing all the advantages of C variables, and end up needing a
    index wider than 8-bits. So 'table' is just memory[120000] to
    memory[120255], and table is just memory[i+120000]; so simple!

    You don't really want to do this sort of stuff in a high-level language.

    >>> Want a 10 bit pointer?
    >>>
    >>> Easy.
    >>>
    >>> char table[1024];
    >>> int pointerInTable; /* Values from 0 to 1023 */

    >>
    >> And that one's not even ten bits. It's more likely 32 bits.
    >>

    >
    > Well, all my pointers in my machine are 35 bits (I have only 12GB of
    > memory) but they use 64... (Ignoring Virtual Memory)


    I think BS was more concerned about choosing 32-bit pointers when the
    natural size was 64-bits. The utilisation of bits was less important, except
    perhaps as a way of packing pointer values.

    >>> Which system are you using?

    >>
    >> Clearly one without a stack, perhaps some lowly controller chip.
    >>

    >
    > Impossible. There isn't a CALL instruction then. It is impossible
    > to implement a CALL without a conceptual stack. Yes, you can "push"
    > your return address into some register but this is conceptually a stack!


    Recursive calls are more difficult. It can be emulated in software as you
    say, but on simple processors you may not need recursiveness.

    And I have programmed a machine without a hardware stack: you had to store a
    return address in memory somewhere where the called routine could pick it up
    to do an indirect jump.

    --
    Bartc
    BartC, Nov 15, 2011
    #7
  8. jacob navia <> writes:
    <snip>
    > Conceptually ANY pointer is an index in a big array called "memory"
    > (or RAM if you like).


    C pointers don't fit this concept. They have a type which contributes
    to the result of operations like *p, sizeof *p and p + 1.

    C's function pointers don't fit well into the "memory index" model
    either because you can do any array-like operations with them.

    <snip>
    --
    Ben.
    Ben Bacarisse, Nov 15, 2011
    #8
  9. Barry Schwarz

    jacob navia Guest

    Le 15/11/11 12:45, Ben Bacarisse a écrit :
    > jacob navia<> writes:
    > <snip>
    >> Conceptually ANY pointer is an index in a big array called "memory"
    >> (or RAM if you like).

    >
    > C pointers don't fit this concept. They have a type which contributes
    > to the result of operations like *p, sizeof *p and p + 1.
    >


    The *p operation is just
    1) Read the value of the pointer
    2) Index the memory
    3) read that position.

    This is just memory[p] (assuming non segmented memory)

    sizeof(*p) <==> sizeof (memory[p]) where you would have
    conceptually "memory" as an aray of *p.

    The "p + 1" operation is the same:
    memory[p+1] where "memory" is an array of objects of type *p.


    > C's function pointers don't fit well into the "memory index" model
    > either because you can do any array-like operations with them.
    >


    Function pointers can be emulated as a conceptual table of
    machine instructions where p points to the start of the
    sequence of instructions of a function.

    In general, what I want to emphasize is the equivalence between array
    indices and pointers.

    And no, pleeze, I do not want to eliminate pointers from C... :)
    jacob navia, Nov 15, 2011
    #9
  10. jacob navia <> writes:

    > Le 15/11/11 12:45, Ben Bacarisse a écrit :
    >> jacob navia<> writes:
    >> <snip>
    >>> Conceptually ANY pointer is an index in a big array called "memory"
    >>> (or RAM if you like).

    >>
    >> C pointers don't fit this concept. They have a type which contributes
    >> to the result of operations like *p, sizeof *p and p + 1.
    >>

    >
    > The *p operation is just
    > 1) Read the value of the pointer
    > 2) Index the memory
    > 3) read that position.
    >
    > This is just memory[p] (assuming non segmented memory)
    >
    > sizeof(*p) <==> sizeof (memory[p]) where you would have
    > conceptually "memory" as an aray of *p.


    But you want to suggest that a pointer in an index into one big array
    called memory. What type does this one big memory array have?

    I know what you mean. The type of the big array will keep changing
    depending on the context, but that just shows why you can't say that a
    pointer "is an index in a big array called 'memory'" -- pointers don't
    fit the concept of an index into an array, because an array has one type
    for all it's elements.

    > The "p + 1" operation is the same:
    > memory[p+1] where "memory" is an array of objects of type *p.


    This last one is wrong, even assuming a magic array whose type can be
    whatever is need at the time.

    >> C's function pointers don't fit well into the "memory index" model
    >> either because you can do any array-like operations with them.

    >
    > Function pointers can be emulated as a conceptual table of
    > machine instructions where p points to the start of the
    > sequence of instructions of a function.


    So you think it's helpful to consider a function pointer to be an index
    into array, but one you can't do any array operations on? How does that
    help? What type is this new array or is it the same as the other array?
    To my mind, this is am attempted simplification that complicates matters.

    > In general, what I want to emphasize is the equivalence between array
    > indices and pointers.


    In general, I don't want to do that.

    --
    Ben.
    Ben Bacarisse, Nov 15, 2011
    #10
  11. Barry Schwarz

    jacob navia Guest

    Le 15/11/11 13:39, Ben Bacarisse a écrit :
    > jacob navia<> writes:
    >
    >> Le 15/11/11 12:45, Ben Bacarisse a écrit :
    >>> jacob navia<> writes:
    >>> <snip>
    >>>> Conceptually ANY pointer is an index in a big array called "memory"
    >>>> (or RAM if you like).
    >>>
    >>> C pointers don't fit this concept. They have a type which contributes
    >>> to the result of operations like *p, sizeof *p and p + 1.
    >>>

    >>
    >> The *p operation is just
    >> 1) Read the value of the pointer
    >> 2) Index the memory
    >> 3) read that position.
    >>
    >> This is just memory[p] (assuming non segmented memory)
    >>
    >> sizeof(*p)<==> sizeof (memory[p]) where you would have
    >> conceptually "memory" as an aray of *p.

    >
    > But you want to suggest that a pointer in an index into one big array
    > called memory. What type does this one big memory array have?
    >
    > I know what you mean. The type of the big array will keep changing
    > depending on the context, but that just shows why you can't say that a
    > pointer "is an index in a big array called 'memory'" -- pointers don't
    > fit the concept of an index into an array, because an array has one type
    > for all it's elements.
    >


    Yes, but you can see a long double as an array of 10 bytes, or 5 shorts,
    or many other representations. That is the "pointed at" type, not
    the value of the pointer itself. The value of the pointer is always the
    value of an index into a byte array starting at virtual memory address
    zero and going on up to the top of the virtual memory space.

    >> The "p + 1" operation is the same:
    >> memory[p+1] where "memory" is an array of objects of type *p.

    >
    > This last one is wrong, even assuming a magic array whose type can be
    > whatever is need at the time.
    >


    That is what I am saying. Suppose

    long double *pLongDouble = &var;

    If you look at the VALUE of that pointer you will read (say)
    0x7DF4500

    What is that number?

    Is the NUMBER of memory locations starting at zero that you should
    skip to arrive at that value. It is NOT the number of doubles,
    or long doubles or the type of whatever that pointer is being used
    for.

    All pointers use the same UNIT: memory locations. Of course they
    dereference different types, etc. But basically they are all the same.

    They are an index into the "memory" array. (Assuming non-segmented
    memory)

    >>> C's function pointers don't fit well into the "memory index" model
    >>> either because you can do any array-like operations with them.

    >>
    >> Function pointers can be emulated as a conceptual table of
    >> machine instructions where p points to the start of the
    >> sequence of instructions of a function.

    >
    > So you think it's helpful to consider a function pointer to be an index
    > into array, but one you can't do any array operations on?


    Look:

    double fn(int a, int b)
    {
    return a+b;
    }

    unsigned char code_for_function_fn[] = {
    0x55,0x89,0xe5,0x57,0x8b,0x7d,0x08,
    0x0",0x7d,0x0c,0x57,0xdb,0x04,0x24,
    0x83,0xc4,0x04,0x5f,0x5d,0xc3};


    Both representations of the function "fn" are identical. The
    proof is that if you disassemble "fn" you will obtain:

    [0000000] 55 push %ebp
    [0000001] 89e5 mov %esp,%ebp
    [0000003] 57 push %edi
    [0000004] 8b7d08 mov 0x8(%ebp),%edi
    [0000007] 037d0c add 0xc(%ebp),%edi
    [0000010] 57 push %edi
    [0000011] db0424 fildl (%esp,1)
    [0000014] 83c404 add $0x4,%esp
    [0000017] 5f pop %edi
    [0000018] 5d pop %ebp
    [0000019] c3 ret


    If you cast the function pointer of "fn" into a char pointer, you can
    even do a memcmp to verify that (obviously the actual contents could
    be different in a different version of lcc-win or with another compiler
    but that is just trivial).

    All functions are just an array of instructions (well, a special array
    since instructions need not to be of the same length)

    > How does that
    > help?


    It helps to avoid being caught by software and to realize that actually
    it is the hardware that does everything.

    It helps because it helps you realize how the machine actually WORKS...

    What type is this new array or is it the same as the other array?

    There is only ONE type for pointers: Memory locations (consecutive
    in a linear architecture, segmented in a "Harvard" architecture)

    > To my mind, this is am attempted simplification that complicates matters.


    Sure, but this is how machines actually WORK.

    >
    >> In general, what I want to emphasize is the equivalence between array
    >> indices and pointers.

    >
    > In general, I don't want to do that.
    >


    You will agree that *p is the same as p[0] isn't it? For ALL p?

    Why is that?

    Anyway, I understand why you do not want to do that in general. Because
    you are concerned with software and with high level languages (that
    exist only in software). And that is a very legitimate concern.

    I am at the interface of software and hardware. My job is to translate
    software into codes that the hardware understands, so I am more
    interested in knowing how a machine actually works beyond software
    abstractions.
    jacob navia, Nov 15, 2011
    #11
  12. jacob navia <> writes:

    > Le 15/11/11 13:39, Ben Bacarisse a écrit :
    >> jacob navia<> writes:
    >>
    >>> Le 15/11/11 12:45, Ben Bacarisse a écrit :
    >>>> jacob navia<> writes:
    >>>> <snip>
    >>>>> Conceptually ANY pointer is an index in a big array called "memory"
    >>>>> (or RAM if you like).
    >>>>
    >>>> C pointers don't fit this concept. They have a type which contributes
    >>>> to the result of operations like *p, sizeof *p and p + 1.
    >>>>
    >>>
    >>> The *p operation is just
    >>> 1) Read the value of the pointer
    >>> 2) Index the memory
    >>> 3) read that position.
    >>>
    >>> This is just memory[p] (assuming non segmented memory)
    >>>
    >>> sizeof(*p)<==> sizeof (memory[p]) where you would have
    >>> conceptually "memory" as an aray of *p.

    >>
    >> But you want to suggest that a pointer in an index into one big array
    >> called memory. What type does this one big memory array have?
    >>
    >> I know what you mean. The type of the big array will keep changing
    >> depending on the context, but that just shows why you can't say that a
    >> pointer "is an index in a big array called 'memory'" -- pointers don't
    >> fit the concept of an index into an array, because an array has one type
    >> for all it's elements.
    >>

    >
    > Yes, but you can see a long double as an array of 10 bytes, or 5 shorts,
    > or many other representations. That is the "pointed at" type, not
    > the value of the pointer itself. The value of the pointer is always
    > the value of an index into a byte array starting at virtual memory
    > address
    > zero and going on up to the top of the virtual memory space.
    >
    >>> The "p + 1" operation is the same:
    >>> memory[p+1] where "memory" is an array of objects of type *p.

    >>
    >> This last one is wrong, even assuming a magic array whose type can be
    >> whatever is need at the time.
    >>

    >
    > That is what I am saying.


    No, look at what you wrote. Even in your world of indexes, p+1 is not
    memory[p+1] as you wrote. You might have meant &memory[p+1] but I don't
    want to guess (and you'd have to say what & means in this big array
    index world).

    > Suppose
    >
    > long double *pLongDouble = &var;
    >
    > If you look at the VALUE of that pointer you will read (say)
    > 0x7DF4500


    Do you know that this is ambiguous? A value (in C) is a pile of bits
    /interpreted as a value of some type/. Do you believe that the value of
    that pointer is always -- on all hardware -- independent of the type
    used to interpret the bits?

    In a debugger, the bits are often interpreted as an unsigned int, so,
    for the time being, I'll assume that this is what you mean by the value
    of a pointer.

    > What is that number?
    >
    > Is the NUMBER of memory locations starting at zero that you should
    > skip to arrive at that value. It is NOT the number of doubles,
    > or long doubles or the type of whatever that pointer is being used
    > for.
    >
    > All pointers use the same UNIT: memory locations. Of course they
    > dereference different types, etc. But basically they are all the same.


    I don't know what this means. What is this UNIT? If you mean that all
    machine addresses use the same measure to determine where they point,
    this is not true. It can depend on the type. C specifically allows for
    different kinds of machine address that may use different units. If
    you've even wandered why C's rules of pointer conversion are the way
    they are, it is largely because of this.

    Note I switched to "machine address" rather than "pointer". You, of all
    people, know that C pointers don't use the same measure, but I think you
    think that once you've moved into the realm of machine addresses, it
    becomes true. It does not (though I grant you it does on all the
    hardware you've probably used).

    > They are an index into the "memory" array. (Assuming non-segmented
    > memory)


    Not all pointers. I've used a machine where function pointers "looked
    like" small numbers. The address of your first function was 0. The
    second was 1, the third 2, and so on. In what useful way are these
    indexes into some giant array called "memory"?

    >>>> C's function pointers don't fit well into the "memory index" model
    >>>> either because you can do any array-like operations with them.
    >>>
    >>> Function pointers can be emulated as a conceptual table of
    >>> machine instructions where p points to the start of the
    >>> sequence of instructions of a function.

    >>
    >> So you think it's helpful to consider a function pointer to be an index
    >> into array, but one you can't do any array operations on?

    >
    > Look:
    >
    > double fn(int a, int b)
    > {
    > return a+b;
    > }
    >
    > unsigned char code_for_function_fn[] = {
    > 0x55,0x89,0xe5,0x57,0x8b,0x7d,0x08,
    > 0x0",0x7d,0x0c,0x57,0xdb,0x04,0x24,
    > 0x83,0xc4,0x04,0x5f,0x5d,0xc3};
    >
    > Both representations of the function "fn" are identical.


    I think you misunderstand the meaning of identical. One is portable
    across machines and the other is not. One can be called without
    undefined behaviour the other can not, and so on.

    > The
    > proof is that if you disassemble "fn" you will obtain:
    >
    > [0000000] 55 push %ebp
    > [0000001] 89e5 mov %esp,%ebp
    > [0000003] 57 push %edi
    > [0000004] 8b7d08 mov 0x8(%ebp),%edi
    > [0000007] 037d0c add 0xc(%ebp),%edi
    > [0000010] 57 push %edi
    > [0000011] db0424 fildl (%esp,1)
    > [0000014] 83c404 add $0x4,%esp
    > [0000017] 5f pop %edi
    > [0000018] 5d pop %ebp
    > [0000019] c3 ret


    Honestly, do you really think I don't how it's usually done? My point
    is that is that it's not /always/ done this way, and that makes the
    "pointer == machine address == index into a big array" model misleading.

    > If you cast the function pointer of "fn" into a char pointer,


    ....you get undefined behaviour.

    > you can
    > even do a memcmp to verify that (obviously the actual contents could
    > be different in a different version of lcc-win or with another compiler
    > but that is just trivial).


    Not without UB.

    > All functions are just an array of instructions (well, a special array
    > since instructions need not to be of the same length)


    but the instructions need not be readable as data, and the pointer might
    not have a representation that relates in any way to a data pointer.

    >> How does that
    >> help?

    >
    > It helps to avoid being caught by software and to realize that actually
    > it is the hardware that does everything.
    >
    > It helps because it helps you realize how the machine actually
    > WORKS...


    You mean how some machines work. I think machine addressing is best
    explained by describing it directly. C deliberately abstracts out all
    the possible differences between (many) machines so it does not work
    well as a way to explain the possibilities.

    > What type is this new array or is it the same as the other array?


    (this is a miss-quote: I said it, not you).

    > There is only ONE type for pointers: Memory locations (consecutive
    > in a linear architecture, segmented in a "Harvard" architecture)


    So on the machine I described above (function pointers being 0, 1, 2
    etc), what is the type of the array into which these are indexes?

    >> To my mind, this is am attempted simplification that complicates matters.

    >
    > Sure, but this is how machines actually WORK.


    It's how many machines work, but you went further. You were using this
    idea to explain C pointers, and they don't work like this.

    >>> In general, what I want to emphasize is the equivalence between array
    >>> indices and pointers.

    >>
    >> In general, I don't want to do that.
    >>

    >
    > You will agree that *p is the same as p[0] isn't it? For ALL p?


    Kinda. It's true in the sense that you get the same result when the
    result is defined, and that both are undefined if either one is
    undefined. Are two "undefined behaviours" always "the same"? A thread
    about that could run and run.

    > Why is that?


    Because the language defines p[0] like that (when both are defined).

    > Anyway, I understand why you do not want to do that in general. Because
    > you are concerned with software and with high level languages (that
    > exist only in software). And that is a very legitimate concern.


    No. I used to teach machine architecture as well, and C hides far
    too much of what is going on to be useful. It's useful to explain how C
    can be implemented on, say, a word addressed machine, but you can't
    illustrate the various address type in C (well, not easily) because
    C, rightly, hides all that.

    > I am at the interface of software and hardware. My job is to translate
    > software into codes that the hardware understands, so I am more
    > interested in knowing how a machine actually works beyond software
    > abstractions.


    Sure, but that does not mean the software abstractions don't exist. If
    this had started as a post about "what the hardware does" it would
    merely be a limited perspective, but you started by saying that C
    pointers are array indexes, and that is sufficiently wrong as to be
    confusing to people learning C.

    --
    Ben.
    Ben Bacarisse, Nov 15, 2011
    #12
  13. jacob navia wrote:

    >
    >
    >>> is it possible using that stack for call of function as
    >>> f(a, b)<=> push32 b|push32 a| call32 f

    >>
    >>
    >> Not on my system which doesn't use a stack or have a push instruction.
    >>

    >
    > Ahh OK;
    >
    >> You shouldn't believe everything you read on Usenet.
    >>

    >
    > You are right. I don't believe you that there isn't (by convention)
    > a register pointing to the stack, and that
    >
    > sub stack,8
    > move value,[stack]
    >
    > doesn't work.
    >
    > Which system are you using?



    I believe ( if I have my Barry's right) that Barry may be working on an IBM
    mainframe.

    We happen to make C/C++ compilers for the mainframe...

    There is no hardware stack (well - technically there is, but it's not very
    convenient and isn't used much.... it's a "newer" addition to the hardware
    and is a little cumbersome to use and pretty much only stacks the
    registers.)

    On the IBM mainframe, programs typically do reserve a register to
    be the "stack pointer" - they call it the "dynamic save area" (DSA).
    Most of the time, this is R13, but that is only by convention.. and many
    programmers choose alternatives.

    There is no "call" instruction - there is a BALR (Branch and Link Register).
    BALR names two registers - the first one receives the address of the
    instruction following the BALR, the 2nd one has the branch target.

    Thus - to effect a "call", you use BALR to jump to the routine. The
    routine
    is then obliged to allocate some space and point R13 to it. It can then
    save the remaining registers along with the return address (loaded into R14
    by the BALR instruction.) You also want to save the previous R13 before
    pointing at the new space.

    (There is a newer variant of the BALR, named BASR - to handle some
    addressing mode situations... newer being, only 20-30 yrs old... BALR
    was part of the original specification.)

    The "allocation of space" can be as simple as pointing R13 at some static
    space in the program; or as complicated as invoking operating system
    services to dynamically allocate space, or having the runtime system
    manage this space by allocating blocks and giving up chunks of the blocks
    as needed.

    Then, on return, you load R13 from the saved location (to restore its
    previous
    value) as well as the other registers... which includes the initial
    value of R14.
    And, you branch back to the location specified in R14. (You may also have
    to de-allocate the space allocated at the start.)

    The act of
    1) Save R13
    2) Point R13 at some new space
    ...
    n) Restore R13 to old value

    clearly is a "stack" in the C sense. But, it is interesting to note that
    this stack is not contiguous. One stack location doesn't necessarily
    have any bearing on another, etc...

    This is by convention only - and many mainframe programming
    environments decide to abandon that convention... making it rather
    frustrating to mix-and-match language implementations or runtime
    environments.

    So - you are partially right - there is by convention a "stack pointer",
    but you can't just subtract a value from it any expect it to work
    in any meaningful fashion.

    There are aveats here - the newer, post 1990 hardware implemented guard
    pages and copy-on-write in the virtual memory addressing system,
    so there are new linkage conventions - called XPLINK, that get
    close to the subtrace-a-value-from-the-stack-pointer paradigm. But, if the
    value you want to subtract is larger than the hardware page size,
    then you still have to "punt out" to an out-of-line routine to allocate
    stack space and move the guard page...

    Also - this all pertains to MVS and z/OS. The z/Linux linkage conventions
    follow the z/Linux ELF ABI, where R15 is the stack pointer... and where
    things work as you might expect.


    - Dave Rivers -

    --
    Work: (919) 676-0847
    Get your mainframe programming tools at http://www.dignus.com
    Thomas David Rivers, Nov 15, 2011
    #13
  14. Barry Schwarz

    BartC Guest

    "jacob navia" <> wrote in message
    news:j9tk3s$7bl$...
    > Le 15/11/11 12:45, Ben Bacarisse a écrit :
    >> jacob navia<> writes:
    >> <snip>
    >>> Conceptually ANY pointer is an index in a big array called "memory"
    >>> (or RAM if you like).

    >>
    >> C pointers don't fit this concept. They have a type which contributes
    >> to the result of operations like *p, sizeof *p and p + 1.
    >>

    >
    > The *p operation is just
    > 1) Read the value of the pointer
    > 2) Index the memory
    > 3) read that position.
    >
    > This is just memory[p] (assuming non segmented memory)



    Yes, you can throw away everything in C, and just have a gigantic static
    array of bytes 'memory'.

    But superimposing ordinary variables, arrays, and structs on top of that is
    fiddly.

    However, even supposing that was done, that's not sufficient, because each
    function invocation will have it's own local byte-array for local variables.
    Now, this array can presumably also be located a space somewhere in the
    global array, but then, so what?

    I'm not sure where you're going with this. You know have control over the
    size and range of pointers, by using indexes (although if memory[] is the
    same size as the machine's memory, the width of your index will be the same
    as the width of your pointers), but you've thrown away half of C too, and
    programming becomes next to impossible.

    Maybe this is how it's all done at a low-level, but I don't think it's what
    that poster had in mind.

    > In general, what I want to emphasize is the equivalence between array
    > indices and pointers.


    Array accesses usually involve two elements: the array, and the index. And
    the array itself will be a pointer (that is, if you forget the nonsense
    about a giant byte-array).

    While pointer accesses usually involve one element, the pointer value, with
    an optional offset.

    And if you have this:

    int A;

    and want to pass a pointer to A to some function, how exactly would you turn
    that into an index, without rewriting your entire application in a
    stripped-down, low-level version of C?

    --
    Bartc
    BartC, Nov 15, 2011
    #14
  15. Ben Bacarisse <> writes:
    > jacob navia <> writes:
    > <snip>
    >> Conceptually ANY pointer is an index in a big array called "memory"
    >> (or RAM if you like).

    >
    > C pointers don't fit this concept. They have a type which contributes
    > to the result of operations like *p, sizeof *p and p + 1.
    >
    > C's function pointers don't fit well into the "memory index" model
    > either because you can do any array-like operations with them.
    >
    > <snip>


    And the C memory model does *not* treat all of memory as a single array.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 15, 2011
    #15
  16. Ben Bacarisse <> writes:
    > jacob navia <> writes:

    [...]
    >> You will agree that *p is the same as p[0] isn't it? For ALL p?

    >
    > Kinda. It's true in the sense that you get the same result when the
    > result is defined, and that both are undefined if either one is
    > undefined. Are two "undefined behaviours" always "the same"? A thread
    > about that could run and run.


    And it's not true of p is a function pointer.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 15, 2011
    #16
  17. Keith Thompson <> writes:

    > Ben Bacarisse <> writes:
    >> jacob navia <> writes:

    > [...]
    >>> You will agree that *p is the same as p[0] isn't it? For ALL p?

    >>
    >> Kinda. It's true in the sense that you get the same result when the
    >> result is defined, and that both are undefined if either one is
    >> undefined. Are two "undefined behaviours" always "the same"? A thread
    >> about that could run and run.

    >
    > And it's not true of p is a function pointer.


    Surely both *p and p[0] are undefined in that case.

    --
    Ben.
    Ben Bacarisse, Nov 15, 2011
    #17
  18. Ben Bacarisse <> writes:
    > Keith Thompson <> writes:
    >> Ben Bacarisse <> writes:
    >>> jacob navia <> writes:

    >> [...]
    >>>> You will agree that *p is the same as p[0] isn't it? For ALL p?
    >>>
    >>> Kinda. It's true in the sense that you get the same result when the
    >>> result is defined, and that both are undefined if either one is
    >>> undefined. Are two "undefined behaviours" always "the same"? A thread
    >>> about that could run and run.

    >>
    >> And it's not true of p is a function pointer.

    >
    > Surely both *p and p[0] are undefined in that case.


    *p is simply a function designator, with the same meaning as p (C99
    6.3.2.1p4). It's sometimes used to make it clear to the reader that p
    is the name of an object of pointer-to-function type, not the name of a
    function.

    p[0] is a constraint violation.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 15, 2011
    #18
  19. Barry Schwarz

    James Kuyper Guest

    On 11/15/2011 04:15 PM, Ben Bacarisse wrote:
    > Keith Thompson <> writes:
    >
    >> Ben Bacarisse <> writes:
    >>> jacob navia <> writes:

    >> [...]
    >>>> You will agree that *p is the same as p[0] isn't it? For ALL p?
    >>>
    >>> Kinda. It's true in the sense that you get the same result when the
    >>> result is defined, and that both are undefined if either one is
    >>> undefined. Are two "undefined behaviours" always "the same"? A thread
    >>> about that could run and run.

    >>
    >> And it's not true of p is a function pointer.

    >
    > Surely both *p and p[0] are undefined in that case.


    If p is a function pointer, 6.5.3.2p4 seem to define *p quite nicely.
    6.3.2.1p4 means that in most cases, *p is exactly equivalent to p,
    rendering it rather pointless, but not undefined.
    James Kuyper, Nov 15, 2011
    #19
  20. Barry Schwarz

    Willem Guest

    Ben Bacarisse wrote:
    ) Keith Thompson <> writes:
    )
    )> Ben Bacarisse <> writes:
    )>> jacob navia <> writes:
    )> [...]
    )>>> You will agree that *p is the same as p[0] isn't it? For ALL p?
    )>>
    )>> Kinda. It's true in the sense that you get the same result when the
    )>> result is defined, and that both are undefined if either one is
    )>> undefined. Are two "undefined behaviours" always "the same"? A thread
    )>> about that could run and run.
    )>
    )> And it's not true of p is a function pointer.
    )
    ) Surely both *p and p[0] are undefined in that case.

    Well, technically what you just said is meaningless, you see,
    'undefined' is not a value that a variable can take in C.

    Pedantically, it is 'undefined behaviour' to access both these values.
    The behaviour need not be the same for those two cases. But then again, it
    need not be the same when you compare the first case with the first case.


    SaSW, Willem
    --
    Disclaimer: I am in no way responsible for any of the statements
    made in the above text. For all I know I might be
    drugged or something..
    No I'm not paranoid. You all think I'm paranoid, don't you !
    #EOT
    Willem, Nov 15, 2011
    #20
    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. Eli Bendersky
    Replies:
    1
    Views:
    1,161
    Mike Treseler
    Mar 1, 2006
  2. Replies:
    7
    Views:
    914
  3. Surinder Singh
    Replies:
    1
    Views:
    1,188
    Richard Bos
    Dec 20, 2007
  4. Casey Hawthorne
    Replies:
    3
    Views:
    1,078
    Flash Gordon
    Nov 1, 2009
  5. Re: A portable stack in C

    , Nov 17, 2011, in forum: C Programming
    Replies:
    20
    Views:
    632
Loading...

Share This Page