Looking for C's equivalent of Pascal's "with"

Discussion in 'C Programming' started by Ruud Baltissen, Oct 2, 2013.

  1. Hello,


    The Pascal equivalent of struct is record. It is possible to nest records inside other records, just like with structs. Assume record Drive0 is nested inside record Device and has the elements InUse and PCfile:

    Device = record
    ...
    ...
    Drive0 = record
    InUse : boolean;
    PCfile : string;
    ...
    end;
    ...
    end;

    If I want to access PCfile of Drive0 I could do it like this:
    Device.Drive0.PCfile := "D:\disk.ima";
    In C it would look about the same. But in Pascal there another way:

    with Device do
    begin
    ...
    ...
    with Drive0 do
    begin
    InUse := True;
    PCfile := "D:\disk.ima";
    end;
    end;

    This comes in handy when handling a lot of elements in one go, for example: when initializing a drive.

    I'm looking for a C equivalent of this "with" construction. All programming examples I saw so far always showed the complete structure. Is there an equivalent or not?

    Thank you for your time and info!


    Kind regards, Ruud Baltissen
    www.Baltissen.org
    Ruud Baltissen, Oct 2, 2013
    #1
    1. Advertising

  2. Ruud Baltissen

    Eric Sosman Guest

    On 10/2/2013 9:35 AM, Ruud Baltissen wrote:
    > Hello,
    >
    >
    > The Pascal equivalent of struct is record. It is possible to nest records inside other records, just like with structs. Assume record Drive0 is nested inside record Device and has the elements InUse and PCfile:
    >
    > Device = record
    > ...
    > ...
    > Drive0 = record
    > InUse : boolean;
    > PCfile : string;
    > ...
    > end;
    > ...
    > end;
    >
    > If I want to access PCfile of Drive0 I could do it like this:
    > Device.Drive0.PCfile := "D:\disk.ima";
    > In C it would look about the same. But in Pascal there another way:
    >
    > with Device do
    > begin
    > ...
    > ...
    > with Drive0 do
    > begin
    > InUse := True;
    > PCfile := "D:\disk.ima";
    > end;
    > end;
    >
    > This comes in handy when handling a lot of elements in one go, for example: when initializing a drive.
    >
    > I'm looking for a C equivalent of this "with" construction. All programming examples I saw so far always showed the complete structure. Is there an equivalent or not?


    There's nothing that lets you omit the entire "provenance"
    of a struct or sub-struct. However, you can use a pointer
    variable to collapse or condense some outer nesting levels.
    For example, here's a struct containing sub-struct elements:

    struct inner {
    int this;
    int that;
    };

    struct outer {
    struct inner one;
    struct inner two;
    struct inner three;
    } instance;

    One way to access the members is to write `instance.one.this'
    and `instance.three.that' and so on. Another is to aim a
    pointer variable at the particular inner struct you care about
    at the moment, and use that instead:

    struct inner *p = &instance.two;
    p->this = 42;
    p->that = 17;

    This technique can collapse additional levels if desired:

    struct atomic {
    double trouble;
    short snort;
    };

    struct inner {
    int this;
    int that;
    struct atomic redThing;
    struct atomic blueThing;
    };

    struct outer {
    struct inner one;
    struct inner two;
    struct inner three;
    } instance;

    struct atomic *q = &instance.three.redThing;
    q->trouble = 3.17;
    q->snort = 0;

    .... instead of `instance.three.redThing.trouble = ...' and so on.

    --
    Eric Sosman
    d
    Eric Sosman, Oct 2, 2013
    #2
    1. Advertising

  3. Ruud Baltissen

    BartC Guest

    "Ruud Baltissen" <> wrote in message
    news:...

    > If I want to access PCfile of Drive0 I could do it like this:


    > Device.Drive0.PCfile := "D:\disk.ima";


    > In C it would look about the same. But in Pascal there another way:
    >
    > with Device do
    > begin
    > ...
    > ...
    > with Drive0 do
    > begin
    > InUse := True;
    > PCfile := "D:\disk.ima";
    > end;
    > end;
    >
    > This comes in handy when handling a lot of elements in one go, for
    > example: when initializing a drive.


    You can use something like this

    struct S drive0 = {.InUse =True, .PCfile = "D:\\disk.ima"};

    (although I've never used it myself). I don't know how it works if drive0 is
    nested; you either have to initialise the whole Device struct, or create
    drive0 as above then just assign it: Device.Drive0 = drive0;

    (I think that can done in one go in with certain C systems.)

    --
    Bartc
    BartC, Oct 2, 2013
    #3
  4. Ruud Baltissen

    Nobody Guest

    On Wed, 02 Oct 2013 06:35:33 -0700, Ruud Baltissen wrote:

    > I'm looking for a C equivalent of this "with" construction. All
    > programming examples I saw so far always showed the complete structure. Is
    > there an equivalent or not?


    No.

    However, given a structure, you can obtain a pointer to any field within
    that structure, then access fields via that pointer. So when dealing with
    nested structures, it's not uncommon to take a pointer to some
    sub-structure and assign it to a variable. You can't make fields appear as
    variables, but you can collapse the top-level variable name and any number
    of intervening levels into a single variable.
    Nobody, Oct 2, 2013
    #4
  5. "BartC" <> writes:

    > "Ruud Baltissen" <> wrote in message
    > news:...
    >
    >> If I want to access PCfile of Drive0 I could do it like this:

    >
    >> Device.Drive0.PCfile := "D:\disk.ima";

    >
    >> In C it would look about the same. But in Pascal there another way:
    >>
    >> with Device do
    >> begin
    >> ...
    >> ...
    >> with Drive0 do
    >> begin
    >> InUse := True;
    >> PCfile := "D:\disk.ima";
    >> end;
    >> end;
    >>
    >> This comes in handy when handling a lot of elements in one go, for
    >> example: when initializing a drive.

    >
    > You can use something like this
    >
    > struct S drive0 = {.InUse =True, .PCfile = "D:\\disk.ima"};
    >
    > (although I've never used it myself). I don't know how it works if drive0 is
    > nested; you either have to initialise the whole Device struct, or create
    > drive0 as above then just assign it: Device.Drive0 = drive0;


    The example given had "..." after the two members explicitly shown.
    That suggested to me that assignment of the whole thing would probably
    be more trouble that it's worth.

    > (I think that can done in one go in with certain C systems.)


    --
    Ben.
    Ben Bacarisse, Oct 2, 2013
    #5
  6. Ruud Baltissen

    BartC Guest

    "Ben Bacarisse" <> wrote in message
    news:...
    > "BartC" <> writes:
    >
    >> "Ruud Baltissen" <> wrote in message


    >>> Device.Drive0.PCfile := "D:\disk.ima";


    >> struct S drive0 = {.InUse =True, .PCfile = "D:\\disk.ima"};


    > The example given had "..." after the two members explicitly shown.
    > That suggested to me that assignment of the whole thing would probably
    > be more trouble that it's worth.


    Possibly, but at least it would replace the repetition of 'Device.Drive0'.

    I suppose the OP can also try this:

    #define DD Device.Drive0

    DD.InUse = True;
    DD.PCfile = "D:\\dis.ima";

    #undef DD

    which at least involved less typing.

    --
    Bartc
    BartC, Oct 2, 2013
    #6
  7. Ruud Baltissen

    Jorgen Grahn Guest

    On Wed, 2013-10-02, Eric Sosman wrote:
    ....
    > One way to access the members is to write `instance.one.this'
    > and `instance.three.that' and so on. Another is to aim a
    > pointer variable at the particular inner struct you care about
    > at the moment, and use that instead:
    >
    > struct inner *p = &instance.two;
    > p->this = 42;
    > p->that = 17;
    >
    > This technique can collapse additional levels if desired:
    >
    > struct atomic {
    > double trouble;
    > short snort;
    > };
    >
    > struct inner {
    > int this;
    > int that;
    > struct atomic redThing;
    > struct atomic blueThing;
    > };
    >
    > struct outer {
    > struct inner one;
    > struct inner two;
    > struct inner three;
    > } instance;
    >
    > struct atomic *q = &instance.three.redThing;
    > q->trouble = 3.17;
    > q->snort = 0;
    >
    > ... instead of `instance.three.redThing.trouble = ...' and so on.


    A personal note:

    I really prefer when people do this. Avoiding temporary pointers can
    rather quickly lead to decreased readability, when the same (or
    deceptively similar) long expression is repeated over and over again.

    fie.foo[bar].baz.bat.barney = something;
    fie.foo[bar].baz.bat.fred = something;
    ...

    In C++ you can use references for this, but a constant pointer in C is
    almost as good.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, Oct 3, 2013
    #7
  8. Ruud Baltissen

    Ian Collins Guest

    wrote:
    > The Pascal "WITH" statement is one of those things that seemed a good
    > idea at the time, but produces highly unreadable code.


    A good analogy for posting via that awful google Usenet interface!

    --
    Ian Collins
    Ian Collins, Oct 3, 2013
    #8
  9. wrote:

    > The Pascal "WITH" statement is one of those things that seemed
    > a good idea at the time, but produces highly unreadable code.
    > The problem is that any identifier within the "WITH" statement
    > could now have a different meaning. So if you use a local
    > variable or global variable within the WITH statement, and
    > then rename or add or remove a member of the struct, your
    > code might continue to compile with totally changed meaning.


    I wonder how it compares to partial qualification in PL/I.
    PL/I allows (as far as I know, inherited from COBOL) structure
    members to be references with partial qualification if it isn't
    ambiguous.

    If you have A.B.C, and there are no other C's in the program,
    then C is enough. If there are, either A.C or B.C might work.

    PL/I also allows moving the subscripts in a structure reference.
    A(I).B(J).C(K) can be written A.B.C(I,J,K) or vice versa.
    (The compiler knows where they go in any case.) This one I
    am more sure came from COBOL. As I understand it, COBOL only
    allows for 1D arrays, so structure nesting is used to generate
    higher dimensionality.

    -- glen
    glen herrmannsfeldt, Oct 3, 2013
    #9
  10. Ruud Baltissen

    Fred K Guest

    On Thursday, October 3, 2013 12:21:27 PM UTC-7, glen herrmannsfeldt wrote:
    > wrote:
    >
    >
    >
    > > The Pascal "WITH" statement is one of those things that seemed

    >
    > > a good idea at the time, but produces highly unreadable code.

    >
    > > The problem is that any identifier within the "WITH" statement

    >
    > > could now have a different meaning. So if you use a local

    >
    > > variable or global variable within the WITH statement, and

    >
    > > then rename or add or remove a member of the struct, your

    >
    > > code might continue to compile with totally changed meaning.

    >
    >
    >
    > I wonder how it compares to partial qualification in PL/I.
    >
    > PL/I allows (as far as I know, inherited from COBOL) structure
    >
    > members to be references with partial qualification if it isn't
    >
    > ambiguous.
    >
    >
    >
    > If you have A.B.C, and there are no other C's in the program,
    >
    > then C is enough.


    What a terrible idea!
    Suppose I have a struct AA containing members a through z, each of which is itself a different kind of struct of, and those structs contained members aa through zz, etc., all of these being defined in different files.

    Then my code says
    int i = www;

    It would be a nightmare trying to find the struct that this instance of www belongs to, especially if some of those modules contained local variables named www.


    <snip>
    Fred K, Oct 4, 2013
    #10
  11. ralph <> writes:
    > On Fri, 4 Oct 2013 11:48:08 -0700 (PDT), Fred K
    > <> wrote:

    [...]
    > Mouse over.
    > Open up menu.
    > Select Definition/Declaration if not the default.
    >
    > What are you using? Clay tablets?
    >
    > -ralph
    > <g>


    No, stone knives and bearskins.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Working, but not speaking, for JetHead Development, Inc.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Oct 5, 2013
    #11
  12. Ruud Baltissen

    Lew Pitcher Guest

    On Friday 04 October 2013 21:43, in comp.lang.c, "Keith Thompson"
    <> wrote:

    > ralph <> writes:
    >> On Fri, 4 Oct 2013 11:48:08 -0700 (PDT), Fred K
    >> <> wrote:

    > [...]
    >> Mouse over.
    >> Open up menu.
    >> Select Definition/Declaration if not the default.
    >>
    >> What are you using? Clay tablets?
    >>
    >> -ralph
    >> <g>

    >
    > No, stone knives and bearskins.


    XKCD #378
    "*Real* programmers use butterflies. They open their hands and let the
    delicate wings flap once. The disturbance ripples outwards, changing the
    flow of the eddy currents in the upper atmosphere. These cause momentary
    pockets of higher-pressure air to form, which act as lenses deflecting
    incoming cosmic rays, focusing them to strike the drive platter and flip
    the desired bit."

    (http://xkcd.com/378/)
    --
    Lew Pitcher
    "In Skills, We Trust"
    PGP public key available upon request
    Lew Pitcher, Oct 5, 2013
    #12
  13. Ruud Baltissen

    Sc0rpi0 Guest


    > If I want to access PCfile of Drive0 I could do it like this:
    > Device.Drive0.PCfile := "D:\disk.ima";
    > In C it would look about the same. But in Pascal there another way:
    >
    > with Device do
    > begin
    > ...
    > ...
    > with Drive0 do
    > begin
    > InUse := True;
    > PCfile := "D:\disk.ima";
    > end;
    > end;
    >


    One more ugly aproach - preprocesor :p

    #define as begin and #undef as end;
    where for example defined D0(a) or D1(a) would become Device.Drive0.a
    or D1(a) would be Device.Drive1.a or something like that :).

    D0(InUse), D0(PCFile) etc.
    Sc0rpi0, Oct 11, 2013
    #13
  14. "Sc0rpi0" <sc[zero]rpi[zero]@scosys[dot]eu.org> writes:

    >> If I want to access PCfile of Drive0 I could do it like this:
    >> Device.Drive0.PCfile := "D:\disk.ima";
    >> In C it would look about the same. But in Pascal there another way:
    >>
    >> with Device do
    >> begin
    >> ...
    >> ...
    >> with Drive0 do
    >> begin
    >> InUse := True;
    >> PCfile := "D:\disk.ima";
    >> end;
    >> end;
    >>

    >
    > One more ugly aproach - preprocesor :p
    >
    > #define as begin and #undef as end;
    > where for example defined D0(a) or D1(a) would become Device.Drive0.a
    > or D1(a) would be Device.Drive1.a or something like that :).
    >
    > D0(InUse), D0(PCFile) etc.


    The use of macros has already been suggested (sorry, I forget who by)
    but the suggestion did not use function-like macros. I think your use
    of them just makes things more complex (D0.InUse is surely simpler than
    D0(InUse)).

    If I try to imagine a situation where the function-like macro can be
    used to construct the symbol (i.e. D(0) becomes the token 'Drive0') then
    I start to think I need to re-write this code!

    --
    Ben.
    Ben Bacarisse, Oct 11, 2013
    #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. Adam

    Pascal-style "types"

    Adam, Feb 19, 2005, in forum: ASP .Net
    Replies:
    3
    Views:
    334
  2. Ivan Vecerina
    Replies:
    1
    Views:
    1,236
    Jerry Coffin
    Oct 21, 2003
  3. Replies:
    6
    Views:
    376
    Moonlit
    Sep 2, 2006
  4. Replies:
    5
    Views:
    373
    Moonlit
    Sep 2, 2006
  5. Replies:
    0
    Views:
    286
Loading...

Share This Page