• C Programming Issue...

    From Black Panther@21:1/186 to All on Sunday, February 02, 2020 15:29:54
    Hi All,

    I've been working on learning how to program in C, and I've run into a roadblock...

    For the last week, I've been trying to get my program to read a binary file, which contains (will contain) the user records for the game. However, the program isn't reading the file properly, and also not saving new records properly.

    Here are some snippets of what I've got right now. I'm sure there is something simple that I'm missing and overlooking...

    snip<=-

    char PlyrFile[15]="rcstdta.ply";

    FILE *fp;
    int FindPlayer(char RN[32]);
    bool ReadPlyr(int I);
    void SavePlyr(int I);
    void setstats();

    int PlyrCount=0;

    #ifdef ODPLAT_WIN32
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpszCmdLine, int nCmdShow)
    #else
    int main(int argc, char *argv[])
    #endif
    {
    Plyr.Index=FindPlayer(od_control.user_name);
    if (Plyr.Index>0) PlayGame();
    else if (Plyr.Index==0)
    {
    setweapons();
    setarmour();
    NewPlyr();
    }
    town();
    }

    int totalrecords()
    {
    int x=0;

    if ((fp = fopen(PlyrFile,"rb")) == NULL)
    {
    fclose(fp);
    fp = fopen(PlyrFile,"wb");
    fclose(fp);
    perror("Error while opening the file.\n");
    od_exit(1,FALSE);
    }
    else
    {
    fseek(fp,-sizeof(Plyr),SEEK_END);
    fread(&Plyr,sizeof(Plyr),1,fp);
    x=Plyr.Index;
    }
    fclose(fp);
    PlyrCount=x;
    return(x);
    }

    void SavePlyr(int I)
    {
    int x;
    od_printf("Now saving record %d\n\r",I);
    od_get_key(TRUE);
    if (I > PlyrCount)
    {
    if ((fp = fopen(PlyrFile,"a+b")) == NULL)
    {
    perror("Error while opening the file.\n\r");
    od_exit(1,FALSE);
    }
    fwrite(&Plyr,sizeof(struct PlyrRec),1,fp);
    fclose(fp);
    }
    else
    {
    if (I==0)
    {
    od_printf("Error in saving info...\n\r");
    getchar();
    }
    if ((fp = fopen(PlyrFile,"wb")) == NULL)
    {
    perror("Error while opening the file.\n");
    od_exit(1,FALSE);
    }
    else
    {
    for (x=1;x<=I;x++)
    {
    fread(&Plyr,sizeof(Plyr),1,fp);
    }
    fwrite(&Plyr,sizeof(struct PlyrRec),1,fp);
    fclose(fp);
    }
    }
    }

    bool ReadPlyr(int I)
    {
    bool Ret=FALSE;
    int x;
    if ((fp = fopen(PlyrFile,"rb")) == NULL)
    {
    perror("Error while opening the file.\n\r");
    od_exit(1,FALSE);
    }
    else
    {
    for (x=1;x<=I;x++)
    {
    fread(&Plyr,sizeof(Plyr),1,fp);
    }
    if (Plyr.Index==I) Ret = TRUE;
    }
    fclose(fp);
    return Ret;
    }

    int FindPlayer(char RN[32])
    {
    int Ret=0;
    int I=1;
    while (ReadPlyr(I) && Ret==0)
    {
    od_clr_scr();
    if (strcmp(Plyr.Name,RN)==0) Ret=Plyr.Index;
    else Ret=0;
    I=I+1;
    }
    if (Ret==0)
    {
    NewPlyr();
    Ret = Plyr.Index;
    }
    return(Ret);
    }

    snip<=-

    Thanks in advance for taking a look at this. Any assistance would be greatly appreciated...


    ... Didja ever stop to think and forget to start again

    ___ MultiMail/Linux v0.51

    --- Mystic BBS/QWK v1.12 A43 2019/03/02 (Linux/64)
    * Origin: Castle Rock BBS - bbs.castlerockbbs.com (21:1/186)
  • From Adept@21:2/108 to Black Panther on Sunday, February 02, 2020 14:58:29
    However, the program isn't reading the file properly, and also not
    saving new records properly.

    So, which errors are you getting? And how is the file not being read
    properly? And how is it being written improperly?

    And can you get a debugger on it to see what's in your variables shortly
    before doing a write, or shortly after reading it in?

    --- Mystic BBS v1.12 A43 2019/03/03 (Windows/64)
    * Origin: Storm BBS (21:2/108)
  • From Black Panther@21:1/186 to Adept on Sunday, February 02, 2020 17:10:24
    On 02 Feb 2020, Adept said the following...

    So, which errors are you getting? And how is the file not being read properly? And how is it being written improperly?

    And can you get a debugger on it to see what's in your variables shortly before doing a write, or shortly after reading it in?

    I'm using Code::Blocks 16.01 under Linux, and the debugger setup kinda
    sucks... The only issue that I'm seeing, is when it tries to access the file,
    I get:
    Cannot open file: iofopen.c
    At iofopen.c:85
    Cannot open file: iofopen.c
    At iofopen.c:86
    Cannot open file: iofopen.c
    At iofopen.c:58

    Then the debugger quits on me...

    I'm still trying to figure out how the debugger works in here... :/


    ---

    Black Panther(RCS)
    Castle Rock BBS

    --- Mystic BBS v1.12 A43 2019/03/02 (Linux/64)
    * Origin: Castle Rock BBS - bbs.castlerockbbs.com (21:1/186)
  • From apam@21:1/126 to Black Panther on Monday, February 03, 2020 10:29:53
    Hi,

    I just got out of bed so not really with it yet :)

    But first glance I notice this line in save player

    if ((fp = fopen(PlyrFile,"wb")) == NULL)

    That will truncate the file, so anything saved will be overwritten.

    This is the save player routine in for honour

    void save_player() {
    #if defined(_MSC_VER) || defined(WIN32)
    int fno = open("players.dat", O_WRONLY | O_CREAT | O_BINARY, 0644);
    #else
    int fno = open("players.dat", O_WRONLY | O_CREAT, 0644);
    #endif
    if (fno == -1) {
    md_exit(-1);
    }
    lseek(fno, sizeof(struct user_info) * player_idx, SEEK_SET);

    write(fno, &info, sizeof(struct user_info));

    close(fno);
    }

    Note how I use open instead of fopen, that uses flags, it also returns
    the file number instead of an fptr.

    You could possibly use fopen(PlyrFile, "a+b") Not sure about that one.

    Andrew

    --- MagickaBBS v0.13alpha (Linux/x86_64)
    * Origin: HappyLand - telnet://magickabbs.com:2023/ (21:1/126)
  • From tenser@21:1/101 to Black Panther on Monday, February 03, 2020 13:56:44
    It's a bit hard to respond using the BBS interface, but I'll try...

    On 02 Feb 2020 at 03:29p, Black Panther pondered and said...

    I've been working on learning how to program in C, and I've run into a roadblock...

    For the last week, I've been trying to get my program to read a binary file, which contains (will contain) the user records for the game. However, the program isn't reading the file properly, and also not
    saving new records properly.

    What, precisely, is it doing, and what do you want it to do? That is,
    is the data simply missing, or is it somehow corrupted?

    One of the first things I'd do is try to look at the actual binary
    file. On a Unix system, one might do this with a tool like `od` or
    `hexdump`. This can help you see whether the data you expect is in
    the file or not.



    if ((fp = fopen(PlyrFile,"wb")) == NULL)

    If I'm reading your code right, this is what you call when you want
    to update an existing record. However, calling `fopen()` with mode
    "wb" will truncate the file if it already exists. You probably want
    "r+b" here, though that won't create the file if it doesn't already
    exist. A sequence that may work for you is something like:

    fp = fopen(PlyrFile, "r+b");
    if (fp == NULL)
    fp = fopen(PlyrFile, "wb");
    if (fp == NULL) {
    // There was some kind of error.
    }

    However, you'll notice that there is a race condition here: suppose
    your program executes the first `fopen` and the file doesn't exist,
    so `fopen` returns NULL. Now, another program comes along and creates `PlyrFile` and writes some data into it. Then your program goes and
    runs the second `fopen`. This time, the file exists, so it is truncated,
    thus destroying the data written by the other program you raced with.

    C11 has added an "x" flag to the mode that would cause the second
    `fopen` to return NULL to handle this kind of problem. As long as no one
    is asynchronously creating _and_ deleting the file, you can safely open
    it with something like:

    fp = fopen(PlyrFile, "r+b");
    if (fp == NULL)
    fp = fopen(PlyrFile, "xwb");
    if (fp == NULL)
    fp = fopen(PlyrFile, "r+b");
    if (fp == NULL) {
    // Some kind of error occurred.
    }

    Anyway...Is the code someplace like github? It would be much easier to
    poke at that way....

    --- Mystic BBS v1.12 A44 2020/02/01 (Windows/32)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From Black Panther@21:1/186 to apam on Sunday, February 02, 2020 19:44:26
    On 03 Feb 2020, apam said the following...

    But first glance I notice this line in save player
    if ((fp = fopen(PlyrFile,"wb")) == NULL)
    That will truncate the file, so anything saved will be overwritten.

    That was put in there to create the file, if it didn't already exist. It may
    be the issue...

    Note how I use open instead of fopen, that uses flags, it also returns
    the file number instead of an fptr.

    I had looked for some information on using open, but what I found wasn't very helpful. Is the file number it returns the status of opening the file?

    You could possibly use fopen(PlyrFile, "a+b") Not sure about that one.

    I do have that when it adds another user record to the file, but it doesn't seem to be working either...

    I'll try to emulate what you have in For Honour, and see how that works for me... It's probably something I've got wrong...


    ---

    Black Panther(RCS)
    Castle Rock BBS

    --- Mystic BBS v1.12 A43 2019/03/02 (Linux/64)
    * Origin: Castle Rock BBS - bbs.castlerockbbs.com (21:1/186)
  • From Adept@21:2/108 to Black Panther on Sunday, February 02, 2020 19:09:03
    I'm using Code::Blocks 16.01 under Linux, and the debugger setup kinda sucks... The only issue that I'm seeing, is when it tries to access the file, I get:
    Cannot open file: iofopen.c
    At iofopen.c:85

    Sounds like it's not looking in the right place for your code, then.

    http://forums.codeblocks.org/index.php?topic=11546.0

    ...says to go to advanced options:
    "Settings -> Compiler and debugger... -> Global compiler settings -> [the compiler you use] -> Other settings" ( the rightmost tab).

    ...and then tick "use full path for source files"

    I imagine you could also put your source files in whatever working directory the code is running from, but that's inelegant at best.

    --- Mystic BBS v1.12 A43 2019/03/03 (Windows/64)
    * Origin: Storm BBS (21:2/108)
  • From apam@21:1/126 to Black Panther on Monday, February 03, 2020 13:16:00
    I had looked for some information on using open, but what I found
    wasn't very helpful. Is the file number it returns the status of
    opening the file?

    The file number is like a handle which represents the file, it's a
    little bit like a file pointer, but more basic. You pass the file number
    to read and write, and close, so the OS knows which file you're talking
    about.

    Andrew

    --- MagickaBBS v0.13alpha (Linux/x86_64)
    * Origin: HappyLand - telnet://magickabbs.com:2023/ (21:1/126)
  • From Spectre@21:3/101 to Black Panther on Monday, February 03, 2020 17:55:00
    So, which errors are you getting? And how is the file not being read properly? And how is it being written improperly?

    I'm using Code::Blocks 16.01 under Linux, and the debugger setup kinda sucks... The only issue that I'm seeing, is when it tries to access the file, I get: Cannot open file: iofopen.c At iofopen.c:85 Cannot
    open file: iofopen.c At iofopen.c:86 Cannot open file: iofopen.c At iofopen.c:58

    Thought... file permissions? Does the file already exist? What if you echo :>testfile and try writing to that? I don't know enough about C to of any
    real value.

    Spec


    *** THE READER V4.50 [freeware]
    --- SuperBBS v1.17-3 (Eval)
    * Origin: Scrawled in haste at The Lower Planes (21:3/101)
  • From tenser@21:1/188 to Black Panther on Monday, February 03, 2020 09:58:25
    On 02 Feb 2020, Black Panther said the following...

    Note how I use open instead of fopen, that uses flags, it also return the file number instead of an fptr.

    I had looked for some information on using open, but what I found wasn't very helpful. Is the file number it returns the status of opening the file?

    `open()` comes from the Unix system call interface. It returns an
    integer called a "file descriptor", which the operating system uses
    to connect the program's notion of an open file with the operating
    system's internal representation of a file.

    In the original Unix implementations, there was a kernel-resident
    table called "the file table" that contained an array of
    `struct file` data structures: these then contained metadata about
    currently open files (number of outstanding references, for example:
    on Unix machines, multiple processes can have the same file open).
    Each process then had an array of pointers to the global file table,
    one for each file the process had open. A file descriptor is an
    index into that table.

    On POSIX systems, file descriptors have an interesting property:
    when you open a file, the returned descriptor points to the first
    available entry in the process's open file table. The implication
    then is that the value of the file descriptor is numerically the
    lowest number available. Some file descriptors are assigned to
    standard usage: fd 0 is the process's "standard input", 1 is
    "standard output" and 2 is "standard error". File redirection on
    Unix takes advantage of this property: if I want to redirect input
    from a file, I can `close(0); open("foo", O_RDONLY);`. If the `open`
    of "foo" succeeds (and I'm not racing against another thread in the
    same process!) then I'm guaranteed that the returned file descriptor
    will be 0. If the `open` call failed, then the returned file
    descriptor will be less than 0. In this case, the global (well,
    thread-local) variable `errno` will be set to some value that describes
    the error. E.g., `EACCESS` to mean appoximately "permission denied".

    But the system call interface is rather inconvenient to use and
    doesn't understand things like "lines", for example. So the Unix
    folks, for the 7th Edition Unix release, wrote a "standard IO"
    library with the higher-level "FILE *" abstraction and it's buffered
    streams.

    You can, of course, combine these two things. For example, I can
    `open` a file and get back a file descriptor, and then use `fdopen`
    to associate that file descriptor with a stream:

    // Open a file for read/write, create it if it doesn't exist.
    // The user can read and write it; group/other can read
    // (subject to umask).
    int fd = open("some.file", O_RDWR | O_CREAT, 0644);
    if (fd < 0) {
    perror("opening 'some.file' failed");
    exit(EXIT_FAILURE);
    }
    FILE *fp = fdopen(fd, "r+b");
    if (fp == NULL) {
    perror("could not associated 'some.name' file with stream");
    exit(EXIT_FAILURE); // exiting will implicitly `close(fd);`
    }
    // Now we can manipulate the file through the associated stream.

    --- Mystic BBS v1.12 A43 2019/03/03 (Raspberry Pi/32)
    * Origin: ACiD Underworld // acidunderworld.com:31337 (21:1/188)
  • From Black Panther@21:1/186 to tenser on Monday, February 03, 2020 21:43:02
    On 03 Feb 2020, tenser said the following...

    `open()` comes from the Unix system call interface. It returns an
    integer called a "file descriptor", which the operating system uses
    to connect the program's notion of an open file with the operating system's internal representation of a file.

    That clears things up a lot! Thank you. I've saved a copy of your message to, so I can refer back to it.

    I probably won't have time to do any work with it tonight, but I hope
    tomorrow night I'll be able to dive in work this out. I did adopt Andrew's
    file saving, but I'm thinking the file reading is still messed up, as I'm
    still getting the unable to open file message.

    Thanks again for the explanation. It's greatly appreciated. :)


    ---

    Black Panther(RCS)
    Castle Rock BBS

    --- Mystic BBS v1.12 A43 2019/03/02 (Linux/64)
    * Origin: Castle Rock BBS - bbs.castlerockbbs.com (21:1/186)
  • From apam@21:1/125 to Black Panther on Tuesday, February 04, 2020 15:43:12
    I probably won't have time to do any work with it tonight, but I
    hope tomorrow night I'll be able to dive in work this out. I did
    adopt Andrew's file saving, but I'm thinking the file reading is
    still messed up, as I'm still getting the unable to open file
    message.

    Feel free to dissect anything on my gitlab if it helps, sometimes I find looking at how others did certain things helps me work backwards and
    figure out where I'm going wrong. I'm not an expert by any means but
    most of my stuff seems to do what it's supposed to (even if it took a
    few goes to get it right :P)

    Andrew

    --- MagickaBBS v0.14alpha (NetBSD/evbarm)
    * Origin: Nocturnal - nocturnal.hopto.org:2023 (21:1/125)
  • From tenser@21:1/101 to Black Panther on Wednesday, February 05, 2020 02:47:38
    On 03 Feb 2020 at 09:43p, Black Panther pondered and said...

    Thanks again for the explanation. It's greatly appreciated. :)

    Anytime! I'm happy to help.

    --- Mystic BBS v1.12 A44 2020/02/02 (Windows/32)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From Black Panther@21:1/186 to apam on Saturday, February 08, 2020 22:06:50
    On 04 Feb 2020, apam said the following...

    Feel free to dissect anything on my gitlab if it helps, sometimes I find looking at how others did certain things helps me work backwards and figure out where I'm going wrong. I'm not an expert by any means but
    most of my stuff seems to do what it's supposed to (even if it took a
    few goes to get it right :P)

    I feel like I'm having a Homer Simpson day... I had "borrowed" your
    save_player function from For Honour, and was still running into problems. I was finally able to figure out where the problem was...

    if (fno == -1)

    is not the same as what I typed...

    if (fno = -1)

    For some reason, if you make it a comparison instead of an assignment, it works! Go figure... :)

    Anyway, It's looking like reading/writing to the player file is now working. Now it's time to get the rest of it running. :)

    Thank you all for your help!


    ---

    Black Panther(RCS)
    Castle Rock BBS

    --- Mystic BBS v1.12 A43 2019/03/02 (Linux/64)
    * Origin: Castle Rock BBS - bbs.castlerockbbs.com (21:1/186)
  • From tenser@21:1/101 to Black Panther on Monday, February 10, 2020 02:33:44
    On 08 Feb 2020 at 10:06p, Black Panther pondered and said...

    problems. I was finally able to figure out where the problem was...

    if (fno == -1)

    is not the same as what I typed...

    if (fno = -1)

    For some reason, if you make it a comparison instead of an assignment, it works! Go figure... :)

    Yes, this is a common complaint for C programmers. Assignment in C
    is an expression, but any non-zero expression is also "true": one of
    the many problems with a weakly-typed language like C.

    A common workaround for this silliness is to avoid comparing the
    return value against any specific value. In particular, if you
    know that the lowest-valued legal file descriptor is 0, then use
    an inequality comparison to probe for the error condition:

    if (fd < 0) {
    // There was an error.
    }

    Then you can't accidentally write, `if (foo = -1)`.

    Many modern compilers will also issue a warning if you have an
    assignment in a conditional. In general, I recommend turning
    on all the warnings you can and making sure your code compiles
    cleanly with them enabled. Under GCC or Clang, I usually use
    `${CC} -Wall -Wextra -Werror`.

    --- Mystic BBS v1.12 A44 2020/02/04 (Windows/32)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From Black Panther@21:1/186 to tenser on Sunday, February 09, 2020 10:54:58
    On 10 Feb 2020, tenser said the following...

    A common workaround for this silliness is to avoid comparing the
    return value against any specific value. In particular, if you
    know that the lowest-valued legal file descriptor is 0, then use
    an inequality comparison to probe for the error condition:

    That makes sense. I've updated my code to reflect: if (fno < 0)

    Then you can't accidentally write, `if (foo = -1)`.

    It was a good learning experience though! ;)

    Many modern compilers will also issue a warning if you have an
    assignment in a conditional. In general, I recommend turning
    on all the warnings you can and making sure your code compiles
    cleanly with them enabled. Under GCC or Clang, I usually use
    `${CC} -Wall -Wextra -Werror`.

    I do have warnings turned on in Code::Blocks. There are some that come up
    that I'm not sure what they mean. I end up having to ask Uncle Google.

    Right now, I've got 4 warnings, but they are for unused variables that I will be including shortly.

    Thank you!


    ---

    Black Panther(RCS)
    Castle Rock BBS

    --- Mystic BBS v1.12 A43 2019/03/02 (Linux/64)
    * Origin: Castle Rock BBS - bbs.castlerockbbs.com (21:1/186)
  • From Bugz@21:4/110 to tenser on Sunday, February 09, 2020 13:07:30
    tenser wrote to Black Panther <=-

    On 08 Feb 2020 at 10:06p, Black Panther pondered and said...

    if (fno == -1)
    ...
    if (fno = -1)

    A common workaround for this silliness is to avoid comparing the
    return value against any specific value. In particular, if you
    know that the lowest-valued legal file descriptor is 0, then use
    an inequality comparison to probe for the error condition:

    I've never heard of that. In "Writing Solid Code" they recommended:

    if ( -1 == fno ) // OK!

    if ( -1 = fno ) // compiler error!

    Put the constant value first, and if you happen to forget an =, you
    get a compiler error.

    Take care,

    bugz


    ... Blow your mind, smoke gunpowder.

    ___ MultiMail/Linux v0.49

    --- Mystic BBS/QWK v1.12 A43 2019/03/02 (Linux/64)
    * Origin: BZ&BZ BBS (21:4/110)
  • From Black Panther@21:1/186 to Bugz on Sunday, February 09, 2020 11:46:50
    On 09 Feb 2020, Bugz said the following...

    I've never heard of that. In "Writing Solid Code" they recommended:

    if ( -1 == fno ) // OK!

    if ( -1 = fno ) // compiler error!

    Put the constant value first, and if you happen to forget an =, you
    get a compiler error.

    That's a good idea. I never thought of doing it that way. I guess, you'd get the compiler error because it's trying to assign fno to an signed integer...

    I never thought coming from Pascal to C would be such a challenge... :)


    ---

    Black Panther(RCS)
    Castle Rock BBS

    --- Mystic BBS v1.12 A43 2019/03/02 (Linux/64)
    * Origin: Castle Rock BBS - bbs.castlerockbbs.com (21:1/186)
  • From Beanzilla@21:4/110 to Black Panther on Sunday, February 09, 2020 14:20:52
    On 09 Feb 2020, Black Panther said the following...

    I've never heard of that. In "Writing Solid Code" they recommended:

    if ( -1 == fno ) // OK!

    if ( -1 = fno ) // compiler error!

    Put the constant value first, and if you happen to forget an =, you get a compiler error.


    This causes the compiler to assign -1 to fno which will always throw an error.

    Take Care,
    Beanzilla

    BZ&BZ BBS (Mystic / Linux x64)
    TELNET bbs.red-green.com:4023
    SSH bbs.red-green.com:4022
    WEB https://bbs.red-green.com

    --- Mystic BBS v1.12 A44 2020/02/04 (Linux/64)
    * Origin: BZ&BZ BBS (21:4/110)
  • From Bugz@21:4/110 to Black Panther on Sunday, February 09, 2020 15:08:52
    Black Panther wrote to Bugz <=-

    On 09 Feb 2020, Bugz said the following...

    I've never heard of that. In "Writing Solid Code" they recommended:
    if ( -1 == fno ) // OK!
    if ( -1 = fno ) // compiler error!
    Put the constant value first, and if you happen to forget an =, you
    get a compiler error.

    That's a good idea. I never thought of doing it that way. I guess,
    you'd get the compiler error because it's trying to assign fno to an signed integer...

    The compiler error is somewhat cryptic, unfortunately:

    error: lvalue required as left operand of assignment

    But basically saying: Hey! I can't assign that a value!

    I never thought coming from Pascal to C would be such a challenge... :)

    Pascal was a long time ago for me (high school). I'm lazy, Pascal wants
    too much typing. :P

    Take care,
    bugz

    ... Really get stoned, drink wet cement.

    ___ MultiMail/Linux v0.49

    --- Mystic BBS/QWK v1.12 A44 2020/02/04 (Linux/64)
    * Origin: BZ&BZ BBS (21:4/110)
  • From Spectre@21:3/101 to Black Panther on Monday, February 10, 2020 07:26:00
    I never thought coming from Pascal to C would be such a challenge... :)

    Did you forget that C was designed by some hiddeously evil people, to be fiendishly difficult to use? :)

    Spec


    *** THE READER V4.50 [freeware]
    --- SuperBBS v1.17-3 (Eval)
    * Origin: Scrawled in haste at The Lower Planes (21:3/101)
  • From Black Panther@21:1/186 to Spectre on Sunday, February 09, 2020 14:27:50
    On 10 Feb 2020, Spectre said the following...

    I never thought coming from Pascal to C would be such a challenge...

    Did you forget that C was designed by some hiddeously evil people, to be fiendishly difficult to use? :)

    I think you're right on that one. In a lot of ways, Pascal was so much
    simpler to use, and was also less cryptic.

    I was just limited as to what I could do with Pascal. There are a lot more options available for C...


    ---

    Black Panther(RCS)
    Castle Rock BBS

    --- Mystic BBS v1.12 A44 2020/02/04 (Linux/64)
    * Origin: Castle Rock BBS - bbs.castlerockbbs.com (21:1/186)
  • From Black Panther@21:1/186 to Bugz on Sunday, February 09, 2020 14:31:54
    On 09 Feb 2020, Bugz said the following...

    The compiler error is somewhat cryptic, unfortunately:

    error: lvalue required as left operand of assignment

    But basically saying: Hey! I can't assign that a value!

    The compiler errors/warnings can be cryptic. I have one now that says:

    warning: suggest parentheses around assignment used as truth value

    The line it's indicating is:

    for (y=x;y=20;y--)

    I'm not sure what it's trying to tell me needs parentheses...

    Pascal was a long time ago for me (high school). I'm lazy, Pascal wants too much typing. :P

    That's when I originally learned it as well. I picked it up again a few years ago. Pascal did seem to be more typing, but it was also less cryptic, in my opinion...


    ---

    Black Panther(RCS)
    Castle Rock BBS

    --- Mystic BBS v1.12 A44 2020/02/04 (Linux/64)
    * Origin: Castle Rock BBS - bbs.castlerockbbs.com (21:1/186)
  • From tenser@21:1/101 to Bugz on Monday, February 10, 2020 10:42:19
    On 09 Feb 2020 at 01:07p, Bugz pondered and said...

    A common workaround for this silliness is to avoid comparing the return value against any specific value. In particular, if you
    know that the lowest-valued legal file descriptor is 0, then use
    an inequality comparison to probe for the error condition:

    I've never heard of that.

    Really? How interesting. There's a school of thought
    says that you should always use the inequality instead
    of and equality operator unless you're _sure_ that the
    return value is exactly some number, or more generally,
    that some number exactly terminates some range, etc.

    In this case, POSIX among others mandates that the
    return value of `open()` be exactly -1 on failure, so
    equality is fine. But I can't see why NOT to use the
    inequality, and further, it may help the compiler
    optimize your code since it can do a comparison against
    zero (a single instruction) instead of a comparison
    against another number (probably two instructions).

    I personally don't find that argument too compelling,
    since the cost of a system call will absolutely dwarf
    the savings.

    In "Writing Solid Code" they recommended:

    if ( -1 == fno ) // OK!

    if ( -1 = fno ) // compiler error!

    That's another technique; those are called "yoda
    conditionals". Those have fallen out of favor
    since compilers can warn on the `foo = bar` pattern
    in a conditional, and best practice has evolved
    away from treating assignment as an expression.

    --- Mystic BBS v1.12 A44 2020/02/04 (Windows/32)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From tenser@21:1/101 to Black Panther on Monday, February 10, 2020 11:00:37
    On 09 Feb 2020 at 11:46a, Black Panther pondered and said...

    That's a good idea. I never thought of doing it that way. I guess, you'd get the compiler error because it's trying to assign fno to an signed integer...

    More precisely, `-1` is not an `lvalue` since it's an integer
    constant. In C, the only things you can assign into are lvalues
    which approximately speaking, are the things that can appear on
    the left-hand side of an assignment operator.

    I never thought coming from Pascal to C would be such a challenge... :)

    In some ways, it may by easier because the C standard is publicly
    available; e.g. http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf
    If in doubt, you can look in the standard and figure out what the
    semantics of something are. You have to speak "Standard-ese" well
    enough to parse it, but that's not too hard after a little while.

    Sadly, the Pascal standard has been largely irrelevant vis actual implementations for several decades, and those implementations are
    de-facto defined by themselves.

    The big things that I remember being differences between Pascal and
    C are, approximately:

    1. In C, IO is provided by a library; in Pascal, it's built in.
    2. When evaluating a `for` loop in C, the termination condition
    is re-evaluated each iteration of the loop, while in Pascal
    it is computed at the start of the loop and cached. While
    that sounds inefficient, it lets you do stuff like walk
    linked lists.
    3. In C, `;` is a statement terminator, whereas in Pascal it
    is a statement separator. Thus, you can do things like,
    if foo <> false then
    begin
    println("foo");
    println("bar")
    end
    (Note no semicolon after `println("bar")`)
    4. In Pascal, an array's size is part of its type (though I
    think that modern variants must give you some kind of slice
    type or variable sized array. One hopes so, anyway; this
    was a major source of criticism in Brian Kernighan's paper,
    "Why Pascal is Not My Favorite Programming Language",
    written after the publication of, "Software Tools in Pascal"
    in 1981. https://www.lysator.liu.se/c/bwk-on-pascal.html
    5. IIRC, by default arrays in Pascal are pass-by-value to
    functions and procedures, whereas in C unadorned array
    references decay into pointers. In this sense, C does
    not support true pass-by-reference; the called function
    receives a pointer value, not a true reference.
    The exception for arrays passed by value in C are to
    embed them in a `struct`, which is pass-by-value in C.
    6. Pascal makes a semantic distinction between procedures
    and functions, while C does not. In C, procedures are
    simply functions that return no value (e.g., `void`).
    7. Pascal is strongly typed; C is weakly typed.

    --- Mystic BBS v1.12 A44 2020/02/04 (Windows/32)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From tenser@21:1/101 to Spectre on Monday, February 10, 2020 11:11:26
    On 10 Feb 2020 at 07:26a, Spectre pondered and said...

    Did you forget that C was designed by some hiddeously evil people, to be fiendishly difficult to use? :)

    That's actually really, really not true. Dennis Ritchie was
    the main designer of C, and he was an incredibly affable and
    humble person. He was universally liked and respected by his
    peers and in language design circles.

    Lots of language designers (including Wirth) have criticized
    C, both rightfully and wrongfully. But I've never heard
    anyone call Dennis "hiddeously evil" (again, including Wirth).

    The proof, they say, is in the pudding. It's remarkable
    how much Wirth's later languages (Modula-2, Oberon) took
    from C, such as the semantics of arrays, and how much C's
    successor languages (Alef, Limbo and Go) took from Pascal.

    By the way, Dennis publicly admitted that the variable
    declaration syntax in C was a mistake, and that Wirth got
    it right in Pascal. That's why Limbo and Go both adopt
    a more Pascal-like syntax.

    --- Mystic BBS v1.12 A44 2020/02/04 (Windows/32)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From tenser@21:1/101 to Black Panther on Monday, February 10, 2020 11:18:06
    On 09 Feb 2020 at 02:27p, Black Panther pondered and said...

    I think you're right on that one. In a lot of ways, Pascal was so much simpler to use, and was also less cryptic.

    Part of this is by design. Pascal was designed as a teaching
    language, and was deliberately simpler and less cryptic (indeed,
    in many ways more verbose). C was designed as a systems
    programming language, and itself descended from several earlier
    languages (nb, B, BCPL, CPL) that its designers were familiar
    with. It was not designed for teaching novices, but for writing
    complex programs (like the Unix kernel) by expert programmers.

    Of course both are Turing complete, and so in some sense each
    is strictly as powerful as the other (e.g., one can write a C
    interpreter in Pascal a Pascal interpreter in C).

    --- Mystic BBS v1.12 A44 2020/02/04 (Windows/32)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From tenser@21:1/101 to Black Panther on Monday, February 10, 2020 11:25:48
    On 09 Feb 2020 at 02:31p, Black Panther pondered and said...

    The compiler errors/warnings can be cryptic. I have one now that says:

    warning: suggest parentheses around assignment used as truth value

    The line it's indicating is:

    for (y=x;y=20;y--)

    This is the same problem as your earlier `if (fno = -1)`. The error
    here is in the conditional part of the `for` loop. I suggest breaking
    it apart into it's three separate expressions. One might do this, for
    example, by rewriting it as `while` loop:

    y = x;
    while (y = 20) // Note, this is assignment, not comparison
    y--;

    That is, the loop will continue as long as `y = 20` evaluates to true.
    But since assignment is an expression, this evaluates to `20`, which
    in a boolean context is true. And since loop conditions expressions
    are evaluated on every iteration of a loop in C, this will reassign
    20 to 'y' on each iteration of the loop. So even though `y--` also
    gets evaluated on each iteration, the loop will never terminate since
    it's termination condition is never reached.

    --- Mystic BBS v1.12 A44 2020/02/04 (Windows/32)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From Black Panther@21:1/186 to tenser on Sunday, February 09, 2020 16:30:32
    On 10 Feb 2020, tenser said the following...

    for (y=x;y=20;y--)

    This is the same problem as your earlier `if (fno = -1)`. The error
    here is in the conditional part of the `for` loop. I suggest breaking

    I noticed this right after posting it... I gotta get out of Pascal mode...

    I can't believe I did it again...


    ---

    Black Panther(RCS)
    Castle Rock BBS

    --- Mystic BBS v1.12 A44 2020/02/04 (Linux/64)
    * Origin: Castle Rock BBS - bbs.castlerockbbs.com (21:1/186)
  • From Spectre@21:3/101 to tenser on Monday, February 10, 2020 10:04:00
    Did you forget that C was designed by some hiddeously evil
    people, to be

    That's actually really, really not true. Dennis Ritchie was the main

    Apologies to Dennis, I'll hereafter think of him as Dennis the Menace instead of Dennis the hiddeously evil.... on the other hand... I'm sure there must be something evil in there.... C is a truly infernal contraption :)

    Spec


    --- SuperBBS v1.17-3 (Eval)
    * Origin: < Scrawled in blood at The Lower Planes > (21:3/101)
  • From Spectre@21:3/101 to Bugz on Monday, February 10, 2020 10:09:00
    Pascal was a long time ago for me (high school). I'm lazy, Pascal wants too much typing. :P

    All I had at High School was an Apple IIe and basic... I didn't know anything about Pascal till I was in my 20's somewhere... was a good fit for me.. but I've probably long forgotten more than I ever knew now...

    Spec


    *** THE READER V4.50 [freeware]
    --- SuperBBS v1.17-3 (Eval)
    * Origin: Scrawled in haste at The Lower Planes (21:3/101)
  • From Spectre@21:3/101 to tenser on Monday, February 10, 2020 10:18:00
    Of course both are Turing complete, and so in some sense each is
    strictly as powerful as the other (e.g., one can write a C
    interpreter in Pascal a Pascal interpreter in C).

    I have a recollection of Borland writing early versions of C in pascal. Not sure where it tipped over and they started using C for it. Not sure of the validity but pascal seems to have predated c by some margin.

    Spec


    *** THE READER V4.50 [freeware]
    --- SuperBBS v1.17-3 (Eval)
    * Origin: Scrawled in haste at The Lower Planes (21:3/101)
  • From tenser@21:1/101 to Spectre on Monday, February 10, 2020 14:47:33
    On 10 Feb 2020 at 10:04a, Spectre pondered and said...

    Apologies to Dennis, I'll hereafter think of him as Dennis the Menace instead of Dennis the hiddeously evil.... on the other hand... I'm sure there must be something evil in there.... C is a truly infernal contraption :)

    He wasn't a menace at all (again, he was a genuinely nice person).
    We lost a giant when he died in 2011.

    --- Mystic BBS v1.12 A44 2020/02/04 (Windows/32)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From tenser@21:1/101 to Spectre on Monday, February 10, 2020 15:20:58
    On 10 Feb 2020 at 10:18a, Spectre pondered and said...

    I have a recollection of Borland writing early versions of C in pascal. Not sure where it tipped over and they started using C for it.

    Almost certainly not true. I saw a talk once where Bob Jervis
    talked about the history of Turbo C (Borland's first C product).
    Jervis implemented the compiler (probably in C with parts in
    assembler) and marketed it as "Wizard C", when it was acquired
    by Borland and rebranded under the Turbo umbrella. Borland had
    been successful with Turbo Pascal, and also release Turbo Basic,
    Turbo Prolog. The Turbo C product rounded out the family.

    Bob Jervis himself seemed like a pretty decent guy.

    Not sure
    of the validity but pascal seems to have predated c by some margin.

    This is true...kinda.

    Pascal dates from 1968, when Wirth started the design. He started
    from his Algol-W language, which had been designed as a successor
    to Algol-60 (but the Algol committee chose the ill-fated Algol-68
    design, instead, which proved to be fatal for Algol as a going
    concern).

    Wirth had implemented it a compiler for his new language for the
    CDC 6000 series machines by 1970; intro courses at ETH were using
    it by 1972. As an aside, the used of 'packed' data in Pascal
    comes from the CDC machine: the 6000 series was _word_-oriented,
    not _byte_ oriented. "Packed" data could be used to store more
    than one data in a single machine word (word size was 60 bits: for
    things like strings this made a lot of sense on early memory
    constrained machines).

    However, this early Pascal would not be easily recognizable to
    someone versed in a modern Pascal dialect, or even someone used
    to Turbo Pascal: all the problems described in Kernighan's
    paper would be in evidence.

    On the other hand, the very first primordial Unix was written in
    assembler for the DEC PDP-7 minicomputer in early 1969. A B
    interpreter first appeared on the PDP-7, followed by a compiler
    (in assembler!). By November 1971 they had moved to a PDP-11/20,
    but the system was still largely in assembly. `nb` (or "New B")
    appeared in here. An early version of C appeared in 1972; by
    1973 it had gained structs and was sufficiently advanced that
    the 4th Edition Unix kernel was rewritten in it.

    By the time of 6th Edition Unix in 1975, it was ubiquitous and
    pretty much all of the PDP-11 assembler had disappeared from Unix.

    In between 6th and 7th Edition, "Typesetter C" appeared, and the
    ill-fated `=+` et al syntax was replaced with modern, `+=`. We
    also got unions and a lot of other interesting stuff.

    By the 7th Edition release in 1979, C would be pretty recognizable
    to modern eyes. Most of the standard library was there, stdio,
    malloc, etc. The first edition of "The C Programming Language"
    by Kernighan and Ritchie had been published the year before.

    Although popular belief has it that 7th Edition was the first to
    be ported to a non-PDP-11 machine (the migration from the PDP-7
    doesn't count: that was a reimplementation, not a port), this
    isn't strictly true: Richard Miller ported 6th Edition to an
    Interdata 7/32 machine. Meanwhile, an independent port to the
    Interdata 8/32 machine was done at Bell Labs; they did not know
    of Miller's work at the time and vice versa. Amusingly, the
    infamous "You are not expected to understand this" comment in
    the 6th Edition source came from the 8/32 porting effort.

    The ANSI committee was formed in 1983 to standardize C and
    produced the first official standard document in 1988,
    ratified in 1989. By this point, C is mostly as it is today.

    So yeah, both languages have a very long history, and are almost contemporaneous (real use starting in 1970-1972 for both).
    However, both have been modified heavily since their inception;
    a programmer working in modern dialects of either language
    would likely find the older dialect very frustrating, much as
    a modern English speaker would find Edwardian English somewhat
    foreign.

    --- Mystic BBS v1.12 A44 2020/02/04 (Windows/32)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From Spectre@21:3/101 to tenser on Monday, February 10, 2020 17:14:00
    Apologies to Dennis, I'll hereafter think of him as Dennis the Menace instead of Dennis the hiddeously evil.... on the other hand... I'm
    sure there must be something evil in there.... C is a truly infernal
    contraption :)

    He wasn't a menace at all (again, he was a genuinely nice person). We
    lost a giant when he died in 2011.

    <Shrug> we all have our own thoughts... I'm not trying to say he's the devil personified... perhaps some crazed masochist, definitely a menace to me :) .. obviously we see him in a very different light.

    Spec


    *** THE READER V4.50 [freeware]
    --- SuperBBS v1.17-3 (Eval)
    * Origin: Scrawled in haste at The Lower Planes (21:3/101)
  • From apam@21:1/126 to Spectre on Monday, February 10, 2020 17:26:13
    Apologies to Dennis, I'll hereafter think of him as
    Dennis the Menace Sp> instead of Dennis the hiddeously
    evil.... on the other hand... I'm Dp> sure there must be
    something evil in there.... C is a truly infernal Sp>
    contraption :)

    He wasn't a menace at all (again, he was a genuinely nice
    person). We lost a giant when he died in 2011.

    <Shrug> we all have our own thoughts... I'm not trying to say he's
    the devil
    personified... perhaps some crazed masochist, definitely a menace
    to me :) .. obviously we see him in a very different light.

    Why a menace to you? Did you know him? Or just don't like C?

    I've not really been following this thread... I really like C, probably
    one of the easiest languages to learn in my opinion because of it's
    simplicity, but whatever.

    I'm guessing you're going for humor, but I don't really think insulting
    people or stuff you don't understand is all that funny. This is like the
    whole "Synchromess" crap from a few months ago. Just say you don't like
    X because you don't understand it, and leave it at that - rather than
    throwing insults and saying stuff is terrible etc etc.

    Yeah, I liked Dennis, though I never knew him.

    Andrew

    --- MagickaBBS v0.13alpha (Linux/x86_64)
    * Origin: HappyLand - telnet://magickabbs.com:2023/ (21:1/126)
  • From tenser@21:1/101 to Spectre on Tuesday, February 11, 2020 03:08:05
    On 10 Feb 2020 at 05:14p, Spectre pondered and said...

    <Shrug> we all have our own thoughts... I'm not trying to say he's the devil personified... perhaps some crazed masochist, definitely a menace
    to me :) .. obviously we see him in a very different light.

    I knew him. I'm sorry, he's just none of the things you're
    describing.

    --- Mystic BBS v1.12 A44 2020/02/04 (Windows/32)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From Bugz@21:4/110 to Black Panther on Monday, February 10, 2020 11:50:23
    Black Panther wrote to Bugz <=-

    The compiler errors/warnings can be cryptic. I have one now that says: warning: suggest parentheses around assignment used as truth value
    The line it's indicating is:

    for (y=x;y=20;y--)

    I'm not sure what it's trying to tell me needs parentheses...

    The compiler is trying to say, I'm expecting a comparison, but I see an assignment.

    // for( init; compare; increment )

    for (y=x; y>=20; y--)

    Or, if you really did want to write an infinite loop:

    for( y=x; (y=20); y-- )

    ^ compiler warning is satisfied. The assignment is in (), y assigned 20,
    and then used in comparison -- which will always be true. This might
    take awhile. ;)

    Pascal was a long time ago for me (high school). I'm lazy, Pascal wants too much typing. :P

    That's when I originally learned it as well. I picked it up again a few years ago. Pascal did seem to be more typing, but it was also less cryptic, in my opinion...

    It's all relative. Assembly for the cryptic win! (Or brainf*** for
    a runner up.)

    With great power (comes complexity) and responsibility.

    {MUHAHAHAHAHA.}

    Take care,
    bugz

    ... It's certainly not my fault, I barely touched it.

    ___ MultiMail/Linux v0.49

    --- Mystic BBS/QWK v1.12 A44 2020/02/04 (Linux/64)
    * Origin: BZ&BZ BBS (21:4/110)
  • From Bugz@21:4/110 to tenser on Monday, February 10, 2020 11:50:23
    tenser wrote to Bugz <=-

    On 09 Feb 2020 at 01:07p, Bugz pondered and said...

    A common workaround for this silliness is to avoid comparing the return value against any specific value. In particular, if you
    know that the lowest-valued legal file descriptor is 0, then use
    an inequality comparison to probe for the error condition:

    I've never heard of that.

    Really? How interesting. There's a school of thought
    says that you should always use the inequality instead
    of and equality operator unless you're _sure_ that the
    return value is exactly some number, or more generally,
    that some number exactly terminates some range, etc.

    Sorry, no, I agree if you are checking a range for errors, don't
    use equality to check every possibility. (*)

    (Use the right tool for the job).

    (*) But if you're checking for just -1, using < 0 (while correct),
    makes other future readers of your code say "Why did you do that?
    What other errors -2, -3, etc, do you know about that we don't?"
    Should we be looking specifically for these? Instead of saying
    "File not found" when the file does exist, we should instead say,
    "File is locked" or "Network error" so our error messages can be
    clearer, rather than a vague "We failed".

    I think code readability is king. *FUTURE* code readability++

    Good error messages are great too. Your users will appreciate it.

    But also keep in mind that it's not a compiler error if you
    reverse your alligator.

    if ( fno < -1 )
    if ( fno > -1 )

    or if you reverse the compares:

    if ( -1 > fno )
    if ( -1 < fno )

    No compiler warnings on any of these. But fastly different meanings.

    If you can have the compiler help you warn or error on simply wrong
    code, I think you should do that.

    equality is fine. But I can't see why NOT to use the
    inequality, and further, it may help the compiler
    optimize your code since it can do a comparison against
    zero (a single instruction) instead of a comparison
    against another number (probably two instructions).

    Because compilers can only optimize against zero comparisons?
    Really?! :P

    I wouldn't make any bets on what gets optimized how these days.

    It really depends on the target cpu. (If it even is a cpu! Maybe
    we're running our C code in the browser with emscripten.) :P

    The only time I'd worry about instruction sizes, is if I'm writing
    for ardrino, where small, tight, hard to read code would be allowed.

    Otherwise, clearly write what you mean.

    Premature optimization is evil.

    In "Writing Solid Code" they recommended:
    if ( -1 == fno ) // OK!
    if ( -1 = fno ) // compiler error!

    That's another technique; those are called "yoda
    conditionals". Those have fallen out of favor
    since compilers can warn on the `foo = bar` pattern
    in a conditional, and best practice has evolved
    away from treating assignment as an expression.

    While I agree that compilers are much better then they were --
    and they rarely get the line numbers wrong these days (thank you
    modern compilers) -- I'm not sure you should depend upon them to catch everything.

    Code defensively. If you have to write C code, use whatever
    techniques you can find to make it harder for "it compiles,
    without warnings, but it isn't ever going to do what I want
    correctly" to occur.

    Take care,
    bugz


    ... KEYBOARD - Hardware used to enter errors into a computer.

    ___ MultiMail/Linux v0.49

    --- Mystic BBS/QWK v1.12 A44 2020/02/04 (Linux/64)
    * Origin: BZ&BZ BBS (21:4/110)
  • From Bugz@21:4/110 to Spectre on Monday, February 10, 2020 11:50:23
    Spectre wrote to Bugz <=-

    All I had at High School was an Apple IIe and basic... I didn't know anything about Pascal till I was in my 20's somewhere... was a good fit for me.. but I've probably long forgotten more than I ever knew now...

    High School was TRS-80 Model III's. And when I was leaving, they were
    getting IBM PCs.

    Ah, the good old days. Ok, maybe just the old days. :P

    Take care,
    bugz

    ... Logic is a wreath of pretty flowers with a very bad odor.

    ___ MultiMail/Linux v0.49

    --- Mystic BBS/QWK v1.12 A44 2020/02/04 (Linux/64)
    * Origin: BZ&BZ BBS (21:4/110)
  • From tenser@21:1/101 to Bugz on Tuesday, February 11, 2020 06:29:15
    On 10 Feb 2020 at 11:50a, Bugz pondered and said...

    Really? How interesting. There's a school of thought
    says that you should always use the inequality instead
    of and equality operator unless you're _sure_ that the
    return value is exactly some number, or more generally,
    that some number exactly terminates some range, etc.

    Sorry, no, I agree if you are checking a range for errors, don't
    use equality to check every possibility. (*)

    (Use the right tool for the job).

    (*) But if you're checking for just -1, using < 0 (while correct),
    makes other future readers of your code say "Why did you do that?
    What other errors -2, -3, etc, do you know about that we don't?"
    Should we be looking specifically for these? Instead of saying
    "File not found" when the file does exist, we should instead say,
    "File is locked" or "Network error" so our error messages can be
    clearer, rather than a vague "We failed".

    That's what `errno` is for. Remember, this is programming
    against the Unix system call interface, which is both well
    specified and defined by multiple standards.

    I think code readability is king. *FUTURE* code readability++

    Indeed. Most Unix programmers are somewhat surprised by
    the `== -1` construct; it's not very common. Commonality
    is a better determinant of readability than otherwise.

    Good error messages are great too. Your users will appreciate it.

    That's what `syserror` and `perror` et al are for.

    But also keep in mind that it's not a compiler error if you
    reverse your alligator.

    Yeah. Don't do that. :-) I mean, that's a straight-up
    logic bug; the other is a typo. You can guard against
    the typo, or you can write the program in such a way
    that you can't get it wrong.

    or if you reverse the compares:

    Ah, but if I reverse the assignment and write `fd = -1;`
    I get the wrong behavior. This line of reasoning applies
    to both constructs.

    If you can have the compiler help you warn or error on simply wrong
    code, I think you should do that.

    That's why you enable warnings that tell you about assignments
    inside of comparisons. Then tell the compiler to turn them into
    errors. :-)

    Because compilers can only optimize against zero comparisons?
    Really?! :P

    That's not at all what I said.

    I wouldn't make any bets on what gets optimized how these days.

    I would and I will. But granted my job demands that I
    understand exactly what a compiler will do with my code at
    a pretty fundamental level.

    With sites like godbolt.org out there, we can even easily see
    what common compilers will do.

    Here's what x86_64 gcc 9.2 does with -Ofast.

    First, for comparison against -1:

    int test(int num) {
    if (num == -1)
    return 1;
    return 0;
    }

    test:
    xorl %eax, %eax
    cmpl $-1, %edi
    sete %al
    ret

    Now for inequality test against 0:

    int test(int num) {
    if (num < 0)
    return 1;
    return 0;
    }

    test:
    movl %edi, %eax
    shrl $31, %eax
    ret

    Trunk `clang` emits the same code, as does icc. Interestingly, MSVC
    2017 with `/Ox` is the worst of the bunch, emitting essentially the
    same code for both versions, though the comparison against zero uses
    the `test ecx,ecx` pattern while comparison against -1 uses a CMP
    and a signed literal. TEST is a cheaper instruction than CMP, and
    shorter, so less pressure on the icache.

    But as I said earlier, this is a bit academic as the cost of the
    system call will massively dwarf any tiny savings in a single
    instruction. I suspect one couldn't even meaningfully measure the
    difference.

    The only time I'd worry about instruction sizes, is if I'm writing
    for ardrino, where small, tight, hard to read code would be allowed.

    Small and tight code doesn't have to be hard to read.

    Otherwise, clearly write what you mean.

    This should be your default always, unless a statistically
    sound measure shows you you should care. And then, optimization
    should aways be guided by an accurate profile.

    While I agree that compilers are much better then they were --
    and they rarely get the line numbers wrong these days (thank you
    modern compilers) -- I'm not sure you should depend upon them to catch everything.

    You should not. However, you _should_ be able to rely on them
    to pick up many simple mistakes.

    Furthermore, when writing code in a language, one should be
    idiomatic (that is, use the idioms common in that language,
    on that platform, etc). For better or worse, I wouldn't
    consider yoda conditionals idiomatic anymore.

    Code defensively. If you have to write C code, use whatever
    techniques you can find to make it harder for "it compiles,
    without warnings, but it isn't ever going to do what I want
    correctly" to occur.

    Better yet, don't program in C if you can avoid it. There
    are too many sharp edges, and 50 years of experience have
    shown us that our best and brightest programmers cannot produce
    well-defined C code without jumping through extraordinary
    hoops.

    The accidental-assignment-in-conditional thing is _an_ issue,
    but far from the only one. And while something like yoda
    conditionals may have helped some years ago before our tools
    caught up on that one, there are other areas where it's really
    difficult to avoid the dreaded undefined behavior.

    One of my favorite examples:

    uint16_t product(uint16_t a, uint16_t b) {
    return a * b;
    }

    Can someone explain to me where the undefined behavior is?

    Another, serving as a hint for the former:

    int foo(int a, int b) {
    if (a < 0) return 1;
    if (b < 0) return 1;
    if (a * b < 0) return 0;
    return 1;
    }

    Is it guaranteed that this function can ever return 0?

    --- Mystic BBS v1.12 A44 2020/02/04 (Windows/32)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From Phoobar@21:2/147 to Bugz on Monday, February 10, 2020 11:57:55
    All I had at High School was an Apple IIe and basic... I didn't know
    High School was TRS-80 Model III's. And when I was leaving, they were getting IBM PCs.

    Graduated from one...if not the worst high schools in Oklahoma. Never laid a hand on any computer until 1983. Originally...had to take a class in BASIC to be able to get a math credit to be able to graduate.

    Started off with a used Sinclair ZX-81 I got for $5 US with no power supply. Had to spend another $5 for an Atari wall wart. From there was into
    Commodores the rest of the decade...including VIC-20/64/64C/Amiga.

    ACME BBS-Member of fsxNet/WWIVNet/SciNet/SpookNet/FidoNet/MicroNet.

    --- Mystic BBS v1.12 A45 2020/02/09 (Windows/32)
    * Origin: ACME BBS-I taut I taw a puddy tat! (21:2/147)
  • From Vk3jed@21:1/109 to Black Panther on Tuesday, February 11, 2020 09:35:00
    On 02-09-20 16:30, Black Panther wrote to tenser <=-

    On 10 Feb 2020, tenser said the following...

    for (y=x;y=20;y--)

    This is the same problem as your earlier `if (fno = -1)`. The error
    here is in the conditional part of the `for` loop. I suggest breaking

    I noticed this right after posting it... I gotta get out of Pascal
    mode...

    Oops. :D

    I'm finding this thread interesting learning. :)


    ... In every revolution, there's one man with a vision. Kirk, stardate unknown === MultiMail/Win v0.51
    --- SBBSecho 3.10-Linux
    * Origin: Freeway BBS Bendigo,Australia freeway.apana.org.au (21:1/109)
  • From Vk3jed@21:1/109 to Spectre on Tuesday, February 11, 2020 09:44:00
    On 02-10-20 10:09, Spectre wrote to Bugz <=-

    Pascal was a long time ago for me (high school). I'm lazy, Pascal wants too much typing. :P

    All I had at High School was an Apple IIe and basic... I didn't know anything about Pascal till I was in my 20's somewhere... was a good fit for me.. but I've probably long forgotten more than I ever knew now...

    I started with Applesoft Basic on the Apple II+ and IIe at school. Not long after, we started using CP/M (the Apples had Z80 cards), and learnt MBASIC and Turbo Pascal. I took particularly well to Pascal, and that proved handy after I left school, because at Uni, we used Turbo Pascal under DOS, initially TP3.01, the same version as we used on CP/M.

    For the next 2 years, I became quite proficient at Pascal, until I discovered that the solitary nature of programming didn't fit who I was, but that's a whole other story, which is still unfolding over 30 years later! :D

    I never made the transition to C as a result, and that was further hampered by some lousy lecturers at the time. My first exposure to Unix was similarly tainted, but picking up Linux in 1995 cured that particular issue. :)

    I'd like to update my Pascal knowledge, and have done a bit of dabbling with FreePascal in the last couple of years, but my need to be active and social limits the amount of time I have available for coding. I'd also like to learn how to do network programming sometime.


    ... Budget: a mathematical confirmation of your suspicions...
    === MultiMail/Win v0.51
    --- SBBSecho 3.10-Linux
    * Origin: Freeway BBS Bendigo,Australia freeway.apana.org.au (21:1/109)
  • From Black Panther@21:1/186 to Bugz on Monday, February 10, 2020 18:32:36
    On 10 Feb 2020, Bugz said the following...

    for (y=x;y=20;y--)
    I'm not sure what it's trying to tell me needs parentheses...

    The compiler is trying to say, I'm expecting a comparison, but I see an assignment.

    Yep. I caught that right after I posted it here... I've given up on smacking myself on the forehead... :)

    It's all relative. Assembly for the cryptic win! (Or brainf*** for
    a runner up.)

    It really is relative. I've tried looking at Assembly. That's as far as I
    got, just trying... :) Haven't really looked at brainf***... Now I'm
    curious... :)


    ---

    Black Panther(RCS)
    Castle Rock BBS

    --- Mystic BBS v1.12 A44 2020/02/04 (Linux/64)
    * Origin: Castle Rock BBS - bbs.castlerockbbs.com (21:1/186)
  • From Black Panther@21:1/186 to Vk3jed on Monday, February 10, 2020 18:41:00
    On 11 Feb 2020, Vk3jed said the following...

    I noticed this right after posting it... I gotta get out of Pascal mode...

    Oops. :D

    Yep. My forehead was so sore from me smacking it... :) (smacking my forehead, just in case that didn't sound right...)

    I'm finding this thread interesting learning. :)

    Me too. I just hope I didn't start a battle between people who know C better than I do...


    ---

    Black Panther(RCS)
    Castle Rock BBS

    --- Mystic BBS v1.12 A44 2020/02/04 (Linux/64)
    * Origin: Castle Rock BBS - bbs.castlerockbbs.com (21:1/186)
  • From Black Panther@21:1/186 to Vk3jed on Monday, February 10, 2020 18:44:26
    On 11 Feb 2020, Vk3jed said the following...

    I started with Applesoft Basic on the Apple II+ and IIe at school. Not

    I also started with Apple Basic on the II+ and IIe. I think I was a senior
    when the school got 2 Apple IIgs systems. They were fast!

    We then went on to Apple Pascal. I really didn't care for it much then...


    ---

    Black Panther(RCS)
    Castle Rock BBS

    --- Mystic BBS v1.12 A44 2020/02/04 (Linux/64)
    * Origin: Castle Rock BBS - bbs.castlerockbbs.com (21:1/186)
  • From Spectre@21:3/101 to tenser on Tuesday, February 11, 2020 12:18:00
    I knew him. I'm sorry, he's just none of the things you're
    describing.

    Ok..


    *** THE READER V4.50 [freeware]
    --- SuperBBS v1.17-3 (Eval)
    * Origin: Scrawled in haste at The Lower Planes (21:3/101)
  • From Vk3jed@21:1/109 to Black Panther on Tuesday, February 11, 2020 14:06:00
    On 02-10-20 18:41, Black Panther wrote to Vk3jed <=-

    Oops. :D

    Yep. My forehead was so sore from me smacking it... :) (smacking my forehead, just in case that didn't sound right...)

    Haha, you managed to dig yourself out of that hole. :D

    I'm finding this thread interesting learning. :)

    Me too. I just hope I didn't start a battle between people who know C better than I do...

    If it continues the way it has, it will be a useful lot of information.


    ... Monogamy leaves a lot to be desired.
    === MultiMail/Win v0.51
    --- SBBSecho 3.10-Linux
    * Origin: Freeway BBS Bendigo,Australia freeway.apana.org.au (21:1/109)
  • From Vk3jed@21:1/109 to Black Panther on Tuesday, February 11, 2020 14:08:00
    On 02-10-20 18:44, Black Panther wrote to Vk3jed <=-

    On 11 Feb 2020, Vk3jed said the following...

    I started with Applesoft Basic on the Apple II+ and IIe at school. Not

    I also started with Apple Basic on the II+ and IIe. I think I was a
    senior when the school got 2 Apple IIgs systems. They were fast!

    The 2gs came out just after I left school, IIRC. I wanted one, but that wasn't going to happen.

    We then went on to Apple Pascal. I really didn't care for it much
    then...

    I never learnt Apple Pascal, it was straight to CP/M and TP for me. ;)


    ... And God said, "Let there be light, but make it quick."
    === MultiMail/Win v0.51
    --- SBBSecho 3.10-Linux
    * Origin: Freeway BBS Bendigo,Australia freeway.apana.org.au (21:1/109)
  • From Bugz@21:4/110 to Black Panther on Tuesday, February 11, 2020 11:04:35
    Black Panther wrote to Bugz <=-

    Yep. I caught that right after I posted it here... I've given up on smacking myself on the forehead... :)

    We've all done the same mistakes. Keep at it, you'll get it. ;)

    Take care,
    Bugz

    ... You must know your limits to break through them.
    ___ MultiMail/Linux v0.49

    --- Mystic BBS/QWK v1.12 A44 2020/02/04 (Linux/64)
    * Origin: BZ&BZ BBS (21:4/110)
  • From Black Panther@21:1/186 to Bugz on Tuesday, February 11, 2020 11:10:44
    On 11 Feb 2020, Bugz said the following...

    We've all done the same mistakes. Keep at it, you'll get it. ;)

    I know that, it just gets a bit frustrating at times... ;)

    I have run into another issue, but it might be something with Code::Blocks.

    When I try to use srand() and rand(), it will compile just fine. When I run
    the program, it will segfault though.

    I try to run in debug, and I'm getting unable to open file random.c.

    The line that's giving me the problems is:

    srand(time(0));
    tmp=(rand() % 100)+1;

    I do have #include <stdlib.h>, but it's acting as though the functions are
    not available. When I try to 'find the declaration of srand()', it states it
    is unable to find...

    Not sure what I'm doing wrong on this one...


    ---

    Black Panther(RCS)
    Castle Rock BBS

    --- Mystic BBS v1.12 A44 2020/02/04 (Linux/64)
    * Origin: Castle Rock BBS - bbs.castlerockbbs.com (21:1/186)
  • From Black Panther@21:1/186 to All on Tuesday, February 11, 2020 14:09:14
    On 11 Feb 2020, Black Panther said the following...

    When I try to use srand() and rand(), it will compile just fine. When I run the program, it will segfault though.

    I try to run in debug, and I'm getting unable to open file random.c.

    Ok, this seems to have cleared. Evidently Code::Blocks was experiencing a SNAFU... Restarted it, and it's working fine now...

    I do have another question. I have a data file that was written by a program
    in Pascal. Is it possible to read this file with C, or should I just recreate the file? The file is an array of records.

    I'm guessing recreating it would be best, as both languages use different formats to save variables...

    Thanks,


    ---

    Black Panther(RCS)
    Castle Rock BBS

    --- Mystic BBS v1.12 A44 2020/02/04 (Linux/64)
    * Origin: Castle Rock BBS - bbs.castlerockbbs.com (21:1/186)
  • From tenser@21:1/101 to Black Panther on Wednesday, February 12, 2020 12:23:41
    On 11 Feb 2020 at 11:10a, Black Panther pondered and said...

    I have run into another issue, but it might be something with Code::Blocks.

    When I try to use srand() and rand(), it will compile just fine. When I run the program, it will segfault though.

    Curious; can you paste the entire code?

    I try to run in debug, and I'm getting unable to open file random.c.

    That might be because a debug build requires access to source
    in order to annotate it with debugging information; it may be
    that the environment you're using doesn't have access to those
    files.

    The line that's giving me the problems is:

    srand(time(0));
    tmp=(rand() % 100)+1;

    What happens if you replace `time(0)` with some constant; say 10?
    The random numbers generated won't be so random; but I'm curious
    if the fault goes away.

    I do have #include <stdlib.h>, but it's acting as though the functions
    are not available. When I try to 'find the declaration of srand()', it states it is unable to find...

    Not sure what I'm doing wrong on this one...

    Sounds like your environment is missing some pieces.

    --- Mystic BBS v1.12 A44 2020/02/04 (Windows/32)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From tenser@21:1/101 to Black Panther on Wednesday, February 12, 2020 12:30:28
    On 11 Feb 2020 at 02:09p, Black Panther pondered and said...

    I do have another question. I have a data file that was written by a program in Pascal. Is it possible to read this file with C, or should I just recreate the file? The file is an array of records.

    Yes, it is possible. You'll have to know something about the
    ABI used by Pascal and how it wrote those records out; specific
    things you'll need to care about are sizes of types and padding
    between record elements, if any, and alignment of the record as
    a whole. If the record has something like a string in it, then
    the representation of the string itself becomes important (e.g.,
    is it a count and then bytes, or what?). Also, the endianness
    of the data might be important if you plan on moving it across
    systems where that varies (e.g., from x86 to SPARC).

    In general, it's easier to work with binary data on a platform
    and in a language, but it's much more durable and portable to
    work with text and some serialization format. Things like JSON
    are really popular for data interchange precisely because you
    don't need care about all these platform-specific details, but
    parsing is harder because, well, you've got to write a parser.
    I wrote up a bit about this here: http://fat-dragon.org/post/json5/

    --- Mystic BBS v1.12 A44 2020/02/04 (Windows/32)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)