Re: is there anything unstandard in the c part here

Discussion in 'C Programming' started by Nick Keighley, Jul 26, 2011.

  1. On Jul 26, 12:45 am, Uno <> wrote:

    > I'm doing a mixed-language exercise, and C is the middle east as far as
    > that goes.


    what does "in the middle east" mean? "has a long history"?


    <snip>

    > It starts with fortran the common C extension:


    Fortran is not a C extension common or otherwise

    <snip>

    > #include <sys/types.h>
    > #include <sys/stat.h>
    > #include <unistd.h>


    non-standard headers. That dont appear to be used.

    > #define RIGHT HERE


    what is this for?

    > #include <stdio.h>
    > #include <limits.h>
    > #include <stdlib.h>
    > #include <string.h>
    >
    > char * testc() {
    >
    >      char * pa;
    >      pa = (char *)malloc (50);
    >      if (pa == NULL)
    >        {
    >       printf ("malloc failed.\n");
    >       exit (EXIT_FAILURE);
    >        }
    >      strcpy((char *)pa, "this sentence is less than fifty bytes.");
    >
    >      return pa;
    >
    > }
    >
    > // gcc -c -Wall -Wextra cfunc2.c -o cfunc.o
    >
    > I tried to follow Heathfield's development in chp 8 of _unleashed_ for
    > memory management.  For obvious reason, I don't free what I've
    > malloc'ed, because then it would suck as a pass.
    >
    > Any comments about the code south of RIGHT HERE are welcome.  Cheers,
    > --
    > Uno
     
    Nick Keighley, Jul 26, 2011
    #1
    1. Advertising

  2. Nick Keighley

    James Kuyper Guest

    On 07/26/2011 03:07 AM, Nick Keighley wrote:
    > On Jul 26, 12:45�am, Uno <> wrote:

    ....
    >> #define RIGHT HERE

    >
    > what is this for?


    see below:

    ....
    >> Any comments about the code south of RIGHT HERE are welcome. �Cheers,


    A better way to do the same thing would have been to put RIGHT HERE is a
    comment:

    // RIGHT HERE
    --
    James Kuyper
     
    James Kuyper, Jul 26, 2011
    #2
    1. Advertising

  3. Nick Keighley

    Uno Guest

    On 07/26/2011 04:29 AM, James Kuyper wrote:
    > On 07/26/2011 03:07 AM, Nick Keighley wrote:
    >> On Jul 26, 12:45�am, Uno<> wrote:

    > ...
    >>> #define RIGHT HERE

    >>
    >> what is this for?

    >
    > see below:
    >
    > ...
    >>> Any comments about the code south of RIGHT HERE are welcome. �Cheers,

    >
    > A better way to do the same thing would have been to put RIGHT HERE is a
    > comment:
    >
    > // RIGHT HERE


    It was for editting, which might not be my strong suit. I'm amazed at
    people who choose a secretarial function in deliberative bodies. I see
    that I forgot to adios the 3 non-standard headers before I did this this
    next step, but who cares.

    I took the cast off the malloc, got no warnings, got no bad behavior.

    I took the cast off the strcpy, got no warnings got no bad behavior.

    $ gcc -c -Wall -Wextra cfunc3.c -o cfunc.o
    $ gfortran -Wall -Wextra caller.o testc.o -o out
    $ ./out
    this sentence is less than fifty bytes.
    $ echo "taking cast off malloc"
    taking cast off malloc
    $ gcc -c -Wall -Wextra cfunc3.c -o cfunc.o
    $ gfortran -Wall -Wextra caller.o testc.o -o out
    $ ./out
    this sentence is less than fifty bytes.
    $ cat cfunc3.c
    #include <stdio.h>
    #include <limits.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <string.h>

    char * testc() {

    char * pa;
    pa = malloc (50);
    if (pa == NULL)
    {
    printf ("malloc failed.\n");
    exit (EXIT_FAILURE);
    }
    strcpy((char *)pa, "this sentence is less than fifty bytes.");

    return pa;
    }

    // gcc -c -Wall -Wextra cfunc3.c -o cfunc.o
    $ echo "taking cast off strcpy"
    taking cast off strcpy
    $ gcc -c -Wall -Wextra cfunc3.c -o cfunc.o
    $ gfortran -Wall -Wextra caller.o testc.o -o out
    $ ./out
    this sentence is less than fifty bytes.
    $ cat cfunc3.c
    #include <stdio.h>
    #include <limits.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <string.h>

    char * testc() {

    char * pa;
    pa = malloc (50);
    if (pa == NULL)
    {
    printf ("malloc failed.\n");
    exit (EXIT_FAILURE);
    }
    strcpy(pa, "this sentence is less than fifty bytes.");

    return pa;
    }

    // gcc -c -Wall -Wextra cfunc3.c -o cfunc.o
    $

    Now, got those headers gone, and I think we all agree that this function
    is standard C. As far as me and my compiler can tell, so has every
    other idea as far as what to cast.

    $ gcc -c -Wall -Wextra cfunc3.c -o cfunc.o
    $ gfortran -Wall -Wextra caller.o testc.o -o out
    $ ./out
    this sentence is less than fifty bytes.
    $ cat cfunc3.c
    // right here begins standard C

    #include <stdio.h>
    #include <limits.h>
    #include <stdlib.h>
    #include <string.h>

    char * testc() {

    char * pa;
    pa = malloc (50);
    if (pa == NULL)
    {
    printf ("malloc failed.\n");
    exit (EXIT_FAILURE);
    }
    strcpy(pa, "this sentence is less than fifty bytes.");

    return pa;
    }

    // gcc -c -Wall -Wextra cfunc3.c -o cfunc.o
    $

    This motivates--not begs--the question: what is the best practice?
    --
    Uno
     
    Uno, Jul 28, 2011
    #3
  4. Uno <> writes:
    <snip>
    > $ gcc -c -Wall -Wextra cfunc3.c -o cfunc.o
    > $ gfortran -Wall -Wextra caller.o testc.o -o out
    > $ ./out
    > this sentence is less than fifty bytes.


    There's no sign here that the program "out" uses the code in "cfunc3.c".
    You might want to check that it really does.

    <snip>
    > char * testc() {


    It's better to write char *testc(void) here.

    >
    > char * pa;
    > pa = malloc (50);
    > if (pa == NULL)
    > {
    > printf ("malloc failed.\n");


    fprintf(stederr, ...) is more usual for error messages.

    > exit (EXIT_FAILURE);
    > }
    > strcpy((char *)pa, "this sentence is less than fifty bytes.");
    >
    > return pa;
    > }


    If you have a utility function:

    void *malloc_or_bust(size_t sz)
    {
    void *p = malloc(sz);
    if (p == NULL) {
    fprintf(stderr, "malloc failed.\n");
    exit(EXIT_FAILURE);
    }
    return p;
    }

    then you can simply write

    char *testc(void)
    {
    return strcpy(malloc_or_bust(50),
    "this sentence is less than fifty bytes.");
    }

    <snip>
    > Now, got those headers gone, and I think we all agree that this
    > function is standard C.


    You might want to use standard C (-std=c99 -pedantic) so as not to end
    up relying on gcc extensions that are not available everywhere. There
    are also more warning options that can point you to potential problems
    even if the code is 100% correct. I often use -Wformat-nonliteral
    -Wcast-align -Wbad-function-cast -Wstrict-prototypes -Wundef -Wcast-qual
    -Wshadow -Wwrite-strings and -Wconversion though this last one can
    produce a lot of warnings.

    > As far as me and my compiler can tell, so has
    > every other idea as far as what to cast.


    Sorry, I can't understand this.

    <snip>
    > This motivates--not begs--the question: what is the best practice?


    Best practice for what?

    --
    Ben.
     
    Ben Bacarisse, Jul 28, 2011
    #4
  5. Nick Keighley

    Joe Pfeiffer Guest

    pete <> writes:

    > Ben Bacarisse wrote:
    >
    >> If you have a utility function:
    >>
    >> void *malloc_or_bust(size_t sz)
    >> {
    >> void *p = malloc(sz);
    >> if (p == NULL) {
    >> fprintf(stderr, "malloc failed.\n");
    >> exit(EXIT_FAILURE);
    >> }
    >> return p;
    >> }
    >>
    >> then you can simply write
    >>
    >> char *testc(void)
    >> {
    >> return strcpy(malloc_or_bust(50),
    >> "this sentence is less than fifty bytes.");
    >> }

    >
    > If malloc_or_bust(50) returns a null pointer within testc,
    > then you have undefined behavior in the strcpy call;
    > and then maybe testc will return a null pointer
    > or maybe it will return "this sentence is less than fifty bytes."
    > or maybe something else will happen.


    How can malloc_bust() return a null pointer? If the pointer is null the
    program exits.
     
    Joe Pfeiffer, Jul 29, 2011
    #5
  6. On Thu, 28 Jul 2011 07:19:53 -0400, Ben Bacarisse <>
    wrote:
    >
    > If you have a utility function:
    >
    > void *malloc_or_bust(size_t sz)
    > {
    > void *p = malloc(sz);
    > if (p == NULL) {
    > fprintf(stderr, "malloc failed.\n");
    > exit(EXIT_FAILURE);
    > }
    > return p;
    > }
    >
    > then you can simply write
    >
    > char *testc(void)
    > {
    > return strcpy(malloc_or_bust(50),
    > "this sentence is less than fifty bytes.");
    > }


    Not picking on Ben here -- this is just the post that got me to notice
    this: This looks like a classic case where strncpy would be safer
    than strcpy. I certainly wouldn't want to rely on the length of
    "this sentence ..." being less than the argument passed to malloc.
    If I were writing something like this, with some reason for not having
    the 50 in a #define, and also some reason for not using
    sizeof "this sentence is less than fifty bytes"
    then I would probably write it as

    size_t size = 50;
    char *p = malloc_or_bust(size);
    strncpy(p, "this sentence is less than fifty bytes", size - 1);
    p[size - 1] = '\0'; // in case "this sentence" is a false sentence

    I've seen way too much unnecessary use of strncpy (including recently
    all-too-common idiom "strncpy(dst, src, strlen(src))" from students),
    but this seems to be a case where its use would be prudent.


    --
    Morris Keesan --
     
    Morris Keesan, Jul 29, 2011
    #6
  7. "Morris Keesan" <> writes:

    > On Thu, 28 Jul 2011 07:19:53 -0400, Ben Bacarisse
    > <> wrote:
    >>
    >> If you have a utility function:
    >>
    >> void *malloc_or_bust(size_t sz)
    >> {
    >> void *p = malloc(sz);
    >> if (p == NULL) {
    >> fprintf(stderr, "malloc failed.\n");
    >> exit(EXIT_FAILURE);
    >> }
    >> return p;
    >> }
    >>
    >> then you can simply write
    >>
    >> char *testc(void)
    >> {
    >> return strcpy(malloc_or_bust(50),
    >> "this sentence is less than fifty bytes.");
    >> }

    >
    > Not picking on Ben here -- this is just the post that got me to notice
    > this: This looks like a classic case where strncpy would be safer
    > than strcpy. I certainly wouldn't want to rely on the length of
    > "this sentence ..." being less than the argument passed to malloc.
    > If I were writing something like this, with some reason for not having
    > the 50 in a #define, and also some reason for not using
    > sizeof "this sentence is less than fifty bytes"
    > then I would probably write it as
    >
    > size_t size = 50;
    > char *p = malloc_or_bust(size);
    > strncpy(p, "this sentence is less than fifty bytes", size - 1);
    > p[size - 1] = '\0'; // in case "this sentence" is a false sentence
    >
    > I've seen way too much unnecessary use of strncpy (including recently
    > all-too-common idiom "strncpy(dst, src, strlen(src))" from students),
    > but this seems to be a case where its use would be prudent.


    I have a pathological hatred for strncpy -- it either does not make a
    string or it pointlessly writes null bytes. In only one case for the
    length does it do what you want!

    I'd use strncat:

    char *dest = malloc_or_bust(size);
    *dest = 0;
    return strncat(dest, "string", size - 1);

    --
    Ben.
     
    Ben Bacarisse, Jul 29, 2011
    #7
  8. Nick Keighley

    Uno Guest

    On 07/28/2011 05:19 AM, Ben Bacarisse wrote:
    > Uno<> writes:
    > <snip>
    >> $ gcc -c -Wall -Wextra cfunc3.c -o cfunc.o
    >> $ gfortran -Wall -Wextra caller.o testc.o -o out
    >> $ ./out
    >> this sentence is less than fifty bytes.

    >
    > There's no sign here that the program "out" uses the code in "cfunc3.c".
    > You might want to check that it really does.


    It does by virtue of being a larger number than cfunc2.c. I have a
    low-rent tool-chain.
    >
    > <snip>
    >> char * testc() {

    >
    > It's better to write char *testc(void) here.



    Thx.

    Here's what I've got now. I think I can only paste as quotation:

    > > $ pwd

    > /home/dan/source/fortran_stuff
    > $ gcc -c -Wall -Wextra cfunc4.c -o cfunc.o
    > $ gcc -c -Wall -Wextra cfunc4.c -o cfunc.o
    > cfunc4.c: In function ‘testc’:
    > cfunc4.c:25: error: expected declaration or statement at end of input
    > $ gcc -c -Wall -Wextra cfunc4.c -o cfunc.o
    > $ cat caller2.f03
    > program test
    > use iso_c_binding
    > implicit none
    > interface
    > function testc() bind(c) result(pa)
    > use iso_c_binding
    > type(c_ptr):: pa
    > end function testc
    > end interface
    > type(c_ptr), target :: pa
    > character(1, c_char),pointer::fpa:))
    > pa = testc()
    > call c_f_pointer(pa, fpa, [50])
    > print*, fpa(1:50)
    > end program test
    > ! gfortran -c -Wall -Wextra caller2.f03 -o caller.o
    > ! gfortran -Wall -Wextra caller.o testc.o -o out
    > $ gfortran -Wall -Wextra caller.o testc.o -o out
    > $ ./out
    > this sentence is less than fifty bytes.
    > $



    > $ cat cfunc4.c
    > // right here begins standard C
    >
    > #include <stdio.h>
    > #include <limits.h>
    > #include <stdlib.h>
    > #include <string.h>
    >
    > void *malloc_or_bust(size_t sz)
    > {
    > void *p = malloc(sz);
    > if (p == NULL) {
    > fprintf(stderr, "malloc failed.\n");
    > exit(EXIT_FAILURE);
    > }
    > return p;
    > }
    >
    >
    > char *testc(void)
    > {
    > return strcpy(malloc_or_bust(50),
    > "this sentence is less than fifty bytes.");
    > }
    >
    > // gcc -c -Wall -Wextra cfunc4.c -o cfunc.o
    >
    >
    >
    > $


    snip

    >> Now, got those headers gone, and I think we all agree that this
    >> function is standard C.

    >
    > You might want to use standard C (-std=c99 -pedantic) so as not to end
    > up relying on gcc extensions that are not available everywhere. There
    > are also more warning options that can point you to potential problems
    > even if the code is 100% correct. I often use -Wformat-nonliteral
    > -Wcast-align -Wbad-function-cast -Wstrict-prototypes -Wundef -Wcast-qual
    > -Wshadow -Wwrite-strings and -Wconversion though this last one can
    > produce a lot of warnings.


    Would the bad cast warning cherp up on any of this?
    >
    >> As far as me and my compiler can tell, so has
    >> every other idea as far as what to cast.

    >
    > Sorry, I can't understand this.
    >
    > <snip>
    >> This motivates--not begs--the question: what is the best practice?

    >
    > Best practice for what?
    >


    The best practice for transmitting a string to fortran caller from C.
    --
    Uno
     
    Uno, Jul 30, 2011
    #8
  9. Nick Keighley

    Uno Guest

    On 07/29/2011 12:16 PM, Morris Keesan wrote:
    > On Thu, 28 Jul 2011 07:19:53 -0400, Ben Bacarisse <>
    > wrote:
    >>
    >> If you have a utility function:
    >>
    >> void *malloc_or_bust(size_t sz)
    >> {
    >> void *p = malloc(sz);
    >> if (p == NULL) {
    >> fprintf(stderr, "malloc failed.\n");
    >> exit(EXIT_FAILURE);
    >> }
    >> return p;
    >> }
    >>
    >> then you can simply write
    >>
    >> char *testc(void)
    >> {
    >> return strcpy(malloc_or_bust(50),
    >> "this sentence is less than fifty bytes.");
    >> }

    >
    > Not picking on Ben here -- this is just the post that got me to notice
    > this: This looks like a classic case where strncpy would be safer
    > than strcpy. I certainly wouldn't want to rely on the length of
    > "this sentence ..." being less than the argument passed to malloc.
    > If I were writing something like this, with some reason for not having
    > the 50 in a #define, and also some reason for not using
    > sizeof "this sentence is less than fifty bytes"
    > then I would probably write it as
    >
    > size_t size = 50;
    > char *p = malloc_or_bust(size);
    > strncpy(p, "this sentence is less than fifty bytes", size - 1);
    > p[size - 1] = '\0'; // in case "this sentence" is a false sentence
    >
    > I've seen way too much unnecessary use of strncpy (including recently
    > all-too-common idiom "strncpy(dst, src, strlen(src))" from students),
    > but this seems to be a case where its use would be prudent.
    >
    >


    Thanks for your comment, Morris.

    $ gcc -c -Wall -Wextra cfunc5.c -o cfunc.o
    $ cat caller2.f03
    program test
    use iso_c_binding
    implicit none
    interface
    function testc() bind(c) result(pa)
    use iso_c_binding
    type(c_ptr):: pa
    end function testc
    end interface
    type(c_ptr), target :: pa
    character(1, c_char),pointer::fpa:))
    pa = testc()
    call c_f_pointer(pa, fpa, [50])
    print*, fpa(1:50)
    end program test
    ! gfortran -c -Wall -Wextra caller2.f03 -o caller.o
    ! gfortran -Wall -Wextra caller.o testc.o -o out
    $ gfortran -Wall -Wextra caller.o testc.o -o out
    $ ./out
    this sentence is less than fifty bytes.
    $ cat cfunc5.c
    // right here begins standard C

    #include <stdio.h>
    #include <limits.h>
    #include <stdlib.h>
    #include <string.h>

    void *malloc_or_bust(size_t sz)
    {
    void *p = malloc(sz);
    if (p == NULL) {
    fprintf(stderr, "malloc failed.\n");
    exit(EXIT_FAILURE);
    }
    return p;
    }


    char *testc(void)
    {
    size_t size = 50;
    char *p = malloc_or_bust(size);
    strncpy(p, "this sentence is less than fifty bytes", size - 1);
    p[size - 1] = '\0'; // in case "this sentence" is a false sentence;
    return p;
    }

    // gcc -c -Wall -Wextra cfunc5.c -o cfunc.o






    $ --
    Uno

    "I have no idea why I could paste into this messaqge but could not to
    the previous. Tja."~~Merrill Jensen during Idiocracy 2011 in the USA.
     
    Uno, Jul 30, 2011
    #9
  10. Uno <> writes:

    > On 07/28/2011 05:19 AM, Ben Bacarisse wrote:
    >> Uno<> writes:

    <snip>
    >>> This motivates--not begs--the question: what is the best practice?

    >>
    >> Best practice for what?
    >>

    > The best practice for transmitting a string to fortran caller from C.


    It's almost always the calling function that determines how you must
    interface with the called language. This applies to best practice as
    much as it does to those things that are required.

    --
    Ben.
     
    Ben Bacarisse, Jul 30, 2011
    #10
  11. Nick Keighley

    Uno Guest

    On 07/30/2011 05:23 AM, Ben Bacarisse wrote:

    > It's almost always the calling function that determines how you must
    > interface with the called language. This applies to best practice as
    > much as it does to those things that are required.
    >


    Ok. Fortran is expecting a c-style pointer to a char. This little
    snippet gives you a feel for it. This is pretty-new syntax, and what
    makes it relevant to c is that fortran said *all* interop is with ISO C.

    type(c_ptr):: pa
    end function testc
    end interface
    type(c_ptr), target :: pa
    character(1, c_char),pointer::fpa:))
    pa = testc()

    ....

    Yes the horror of not seeing semicolons, but again I put the fortran
    stuff at the top, so it can disappear with a reasonable edit.

    On the C side, I think I've got something that works well, but I don't
    know that without some code review. This is what dinkumware has for
    strncpy; does anyone have a mnemonic for what the 'n' might mean?

    strncpy

    char *strncpy(char *restrict s1, const char *restrict s2, size_t n);

    The function copies the string s2, not including its terminating null
    character, to successive elements of the array of char whose first
    element has the address s1. It copies no more than n characters from s2.
    The function then stores zero or more null characters in the next
    elements to be altered in s1 until it stores a total of n characters. It
    returns s1.

    So I want a char * before i get to this statement, and that leaves the
    malloc:

    char *p = malloc(sz);

    The reason that I might put it on the left is that I haven't been handed
    anything that's broken, and if it doesn't draw warnings, then C might be
    just fine this.

    Another version might be:

    char *p = (char *)malloc(sz);
    , and I'm naive enough not to see anything wrong there, technically.
    But as I'm sitting here, it looks like an unnecessary cast.

    $ gcc -c -Wall -Wextra cfunc6.c -o cfunc.o
    $ gfortran -c -Wall -Wextra caller2.f03 -o caller.o
    $ gfortran -Wall -Wextra caller.o testc.o -o out
    $ ./out
    this sentence is less than fifty bytes.
    $ cat caller2.f03
    program test
    use iso_c_binding
    implicit none
    interface
    function testc() bind(c) result(pa)
    use iso_c_binding
    type(c_ptr):: pa
    end function testc
    end interface
    type(c_ptr), target :: pa
    character(1, c_char),pointer::fpa:))
    pa = testc()
    call c_f_pointer(pa, fpa, [50])
    print*, fpa(1:50)
    end program test
    ! gfortran -c -Wall -Wextra caller2.f03 -o caller.o
    ! gfortran -Wall -Wextra caller.o testc.o -o out

    $ indent -i3 cfunc6.c

    $ cat cfunc6.c
    #include <stdio.h>
    #include <limits.h>
    #include <stdlib.h>
    #include <string.h>
    char *
    malloc_or_bust (size_t sz)
    {
    char *p = malloc (sz);
    if (p == NULL)
    {
    fprintf (stderr, "malloc failed.\n");
    exit (EXIT_FAILURE);
    }
    return p;
    }
    char *
    testc (void)
    {
    size_t size = 50;
    char *p = malloc_or_bust (size);
    strncpy (p, "this sentence is less than fifty bytes", size - 1);
    p[size - 1] = '\0
    return p;
    }
    // gcc -c -Wall -Wextra cfunc6.c -o cfunc.o
    $

    Thanks for your comment. How long have I known you now? I bet that
    neither of us would move back to Michigan now. what's going on in
    upper-midwest states is shocking. The KKK and arsonists have showed up
    in 'Sconi ten days before people were almost going to have a free and
    fair election.

    --
    Uno
     
    Uno, Aug 1, 2011
    #11
  12. Nick Keighley

    Ike Naar Guest

    On 2011-08-01, Uno <> wrote:
    > $ gcc -c -Wall -Wextra cfunc6.c -o cfunc.o
    > $ gfortran -c -Wall -Wextra caller2.f03 -o caller.o
    > $ gfortran -Wall -Wextra caller.o testc.o -o out


    What is testc.o ?
    Is it related to cfunc6.c ?

    > $ ./out
    > this sentence is less than fifty bytes.


    Just curious: where are the leading spaces and the trailing dot from?

    > [snip fortran code]


    > $ cat cfunc6.c
    > #include <stdio.h>
    > #include <limits.h>
    > #include <stdlib.h>
    > #include <string.h>
    > char *
    > malloc_or_bust (size_t sz)
    > {
    > char *p = malloc (sz);
    > if (p == NULL)
    > {
    > fprintf (stderr, "malloc failed.\n");
    > exit (EXIT_FAILURE);
    > }
    > return p;
    > }
    > char *
    > testc (void)
    > {
    > size_t size = 50;
    > char *p = malloc_or_bust (size);
    > strncpy (p, "this sentence is less than fifty bytes", size - 1);
    > p[size - 1] = '\0
    > return p;
    > }
    > // gcc -c -Wall -Wextra cfunc6.c -o cfunc.o


    $ gcc -c -Wall -Wextra cfunc6.c -o cfunc.o
    cfunc6.c: In function 'testc':
    cfunc6.c:22: error: missing terminating ' character
    cfunc6.c:23: error: expected expression before 'return'
    cfunc6.c:24: warning: control reaches end of non-void function
     
    Ike Naar, Aug 1, 2011
    #12
  13. Uno <> writes:

    > On 07/30/2011 05:23 AM, Ben Bacarisse wrote:
    >
    >> It's almost always the calling function that determines how you must
    >> interface with the called language. This applies to best practice as
    >> much as it does to those things that are required.


    I made a mistake. I meant to say "the calling language" not "the
    calling function". The point being you need to ask Fortran people about
    the best practice.

    > Ok. Fortran is expecting a c-style pointer to a char. This little
    > snippet gives you a feel for it. This is pretty-new syntax, and what
    > makes it relevant to c is that fortran said *all* interop is with ISO
    > C.


    The C has been discussed and you've decided not to use ISO C for some
    reason so what more is there to say here? To get an answer to your
    question about best practice you need to ask Fortran people, not C
    people. Make sure you tell them what you are trying to do because the
    Fortran code you have looks wrong to me.

    > type(c_ptr):: pa
    > end function testc
    > end interface
    > type(c_ptr), target :: pa
    > character(1, c_char),pointer::fpa:))
    > pa = testc()
    >
    > ...
    >
    > Yes the horror of not seeing semicolons, but again I put the fortran
    > stuff at the top, so it can disappear with a reasonable edit.
    >
    > On the C side, I think I've got something that works well, but I don't
    > know that without some code review. This is what dinkumware has for
    > strncpy; does anyone have a mnemonic for what the 'n' might mean?


    What do you mean "might mean"? You know what it means because you quote
    the documentation:

    > strncpy
    >
    > char *strncpy(char *restrict s1, const char *restrict s2, size_t n);
    >
    > The function copies the string s2, not including its terminating null
    > character, to successive elements of the array of char whose first
    > element has the address s1. It copies no more than n characters from
    > s2. The function then stores zero or more null characters in the next
    > elements to be altered in s1 until it stores a total of n
    > characters. It returns s1.
    >
    > So I want a char * before i get to this statement, and that leaves the
    > malloc:
    >
    > char *p = malloc(sz);


    There are other ways to get a char *. You can use static storage or you
    can have the pointer to some storage passed in. You could even be
    passed a pointer to a pointer that you assign from the C function.
    Which is considered best practice is something that the Fortran people
    can advice you about.

    > The reason that I might put it on the left is that I haven't been
    > handed anything that's broken, and if it doesn't draw warnings, then C
    > might be just fine this.
    >
    > Another version might be:
    >
    > char *p = (char *)malloc(sz);
    > , and I'm naive enough not to see anything wrong there,
    > technically. But as I'm sitting here, it looks like an unnecessary
    > cast.


    Yes, it's unnecessary.

    > $ gcc -c -Wall -Wextra cfunc6.c -o cfunc.o
    > $ gfortran -c -Wall -Wextra caller2.f03 -o caller.o
    > $ gfortran -Wall -Wextra caller.o testc.o -o out
    > $ ./out
    > this sentence is less than fifty bytes.


    This can't be the output of the program you show below. For one thing,
    the C has a syntax error and for another there's an extra '.' here.
    You've told me that despite appearances, the commands you show do
    actually use cfunc.o but I am beginning to doubt that. Where does the
    '.' come from.

    When the C syntax error is fixed you still don't get what I think you
    want:

    $ /out | cat -A
    this sentence is less than fifty bytes^@^@^@^@^@^@^@^@^@^@^@^@$

    The Fortran people can help you fix that (unless you do want this
    odd behaviour).

    <snip>
    > char *
    > testc (void)
    > {
    > size_t size = 50;
    > char *p = malloc_or_bust (size);
    > strncpy (p, "this sentence is less than fifty bytes", size - 1);
    > p[size - 1] = '\0


    '; is missing here.

    > return p;
    > }


    <snip>
    --
    Ben.
     
    Ben Bacarisse, Aug 1, 2011
    #13
  14. Nick Keighley

    Uno Guest

    On 08/01/2011 01:50 AM, Ike Naar wrote:
    > On 2011-08-01, Uno<> wrote:
    >> $ gcc -c -Wall -Wextra cfunc6.c -o cfunc.o
    >> $ gfortran -c -Wall -Wextra caller2.f03 -o caller.o
    >> $ gfortran -Wall -Wextra caller.o testc.o -o out

    >
    > What is testc.o ?
    > Is it related to cfunc6.c ?
    >
    >> $ ./out
    >> this sentence is less than fifty bytes.

    >
    > Just curious: where are the leading spaces and the trailing dot from?
    >
    >> [snip fortran code]

    >
    >> $ cat cfunc6.c
    >> #include<stdio.h>
    >> #include<limits.h>
    >> #include<stdlib.h>
    >> #include<string.h>
    >> char *
    >> malloc_or_bust (size_t sz)
    >> {
    >> char *p = malloc (sz);
    >> if (p == NULL)
    >> {
    >> fprintf (stderr, "malloc failed.\n");
    >> exit (EXIT_FAILURE);
    >> }
    >> return p;
    >> }
    >> char *
    >> testc (void)
    >> {
    >> size_t size = 50;
    >> char *p = malloc_or_bust (size);
    >> strncpy (p, "this sentence is less than fifty bytes", size - 1);
    >> p[size - 1] = '\0
    >> return p;
    >> }
    >> // gcc -c -Wall -Wextra cfunc6.c -o cfunc.o

    >
    > $ gcc -c -Wall -Wextra cfunc6.c -o cfunc.o
    > cfunc6.c: In function 'testc':
    > cfunc6.c:22: error: missing terminating ' character
    > cfunc6.c:23: error: expected expression before 'return'
    > cfunc6.c:24: warning: control reaches end of non-void function


    I don't know know how that one got away from me.

    $ gcc -c -Wall -Wextra cfunc7.c -o cfunc.o
    $ gfortran -c -Wall -Wextra caller2.f03 -o caller.o
    $ gfortran -Wall -Wextra caller.o testc.o -o out
    $ ./out
    this sentence is less than fifty bytes.
    $ cat caller2.f03
    program test
    use iso_c_binding
    implicit none
    interface
    function testc() bind(c) result(pa)
    use iso_c_binding
    type(c_ptr):: pa
    end function testc
    end interface
    type(c_ptr), target :: pa
    character(1, c_char),pointer::fpa:))
    pa = testc()
    call c_f_pointer(pa, fpa, [50])
    print*, fpa(1:50)
    end program test
    ! gfortran -c -Wall -Wextra caller2.f03 -o caller.o
    ! gfortran -Wall -Wextra caller.o testc.o -o out
    $ cat cfunc7.c
    #include <stdio.h>
    #include <limits.h>
    #include <stdlib.h>
    #include <string.h>
    char *
    malloc_or_bust (size_t sz)
    {
    char *p = malloc (sz);
    if (p == NULL)
    {
    fprintf (stderr, "malloc failed.\n");
    exit (EXIT_FAILURE);
    }
    return p;
    }
    char *
    testc (void)
    {
    size_t size = 50;
    char *p = malloc_or_bust (size);
    strncpy (p, "this sentence is less than fifty bytes", size - 1);
    p[size - 1] = '\0';
    return p;
    }
    // gcc -c -Wall -Wextra cfunc7.c -o cfunc.o
    $

    --
    Uno
     
    Uno, Aug 1, 2011
    #14
  15. Nick Keighley

    Uno Guest

    On 08/01/2011 07:27 AM, Ben Bacarisse wrote:
    > Uno<> writes:
    >
    >> On 07/30/2011 05:23 AM, Ben Bacarisse wrote:
    >>
    >>> It's almost always the calling function that determines how you must
    >>> interface with the called language. This applies to best practice as
    >>> much as it does to those things that are required.

    >
    > I made a mistake. I meant to say "the calling language" not "the
    > calling function". The point being you need to ask Fortran people about
    > the best practice.


    They either don't know or don't want to share.
    >
    >> Ok. Fortran is expecting a c-style pointer to a char. This little
    >> snippet gives you a feel for it. This is pretty-new syntax, and what
    >> makes it relevant to c is that fortran said *all* interop is with ISO
    >> C.

    >
    > The C has been discussed and you've decided not to use ISO C for some
    > reason so what more is there to say here? To get an answer to your
    > question about best practice you need to ask Fortran people, not C
    > people. Make sure you tell them what you are trying to do because the
    > Fortran code you have looks wrong to me.


    How do you figure that I'm not using iso C? Is this a criticism of the
    fortran part, the C part, or the lack of critical distinction between
    the two?
    >
    >> type(c_ptr):: pa
    >> end function testc
    >> end interface
    >> type(c_ptr), target :: pa
    >> character(1, c_char),pointer::fpa:))
    >> pa = testc()
    >>
    >> ...
    >>
    >> Yes the horror of not seeing semicolons, but again I put the fortran
    >> stuff at the top, so it can disappear with a reasonable edit.
    >>
    >> On the C side, I think I've got something that works well, but I don't
    >> know that without some code review. This is what dinkumware has for
    >> strncpy; does anyone have a mnemonic for what the 'n' might mean?

    >
    > What do you mean "might mean"? You know what it means because you quote
    > the documentation:


    N: null, not null, not null newline....
    >
    >> strncpy
    >>
    >> char *strncpy(char *restrict s1, const char *restrict s2, size_t n);
    >>
    >> The function copies the string s2, not including its terminating null
    >> character, to successive elements of the array of char whose first
    >> element has the address s1. It copies no more than n characters from
    >> s2. The function then stores zero or more null characters in the next
    >> elements to be altered in s1 until it stores a total of n
    >> characters. It returns s1.
    >>
    >> So I want a char * before i get to this statement, and that leaves the
    >> malloc:
    >>
    >> char *p = malloc(sz);

    >
    > There are other ways to get a char *. You can use static storage or you
    > can have the pointer to some storage passed in. You could even be
    > passed a pointer to a pointer that you assign from the C function.
    > Which is considered best practice is something that the Fortran people
    > can advice you about.
    >
    >> The reason that I might put it on the left is that I haven't been
    >> handed anything that's broken, and if it doesn't draw warnings, then C
    >> might be just fine this.
    >>
    >> Another version might be:
    >>
    >> char *p = (char *)malloc(sz);
    >> , and I'm naive enough not to see anything wrong there,
    >> technically. But as I'm sitting here, it looks like an unnecessary
    >> cast.

    >
    > Yes, it's unnecessary.


    Ok.
    >
    >> $ gcc -c -Wall -Wextra cfunc6.c -o cfunc.o
    >> $ gfortran -c -Wall -Wextra caller2.f03 -o caller.o
    >> $ gfortran -Wall -Wextra caller.o testc.o -o out
    >> $ ./out
    >> this sentence is less than fifty bytes.

    >
    > This can't be the output of the program you show below. For one thing,
    > the C has a syntax error and for another there's an extra '.' here.
    > You've told me that despite appearances, the commands you show do
    > actually use cfunc.o but I am beginning to doubt that. Where does the
    > '.' come from.
    >
    > When the C syntax error is fixed you still don't get what I think you
    > want:
    >
    > $ /out | cat -A
    > this sentence is less than fifty bytes^@^@^@^@^@^@^@^@^@^@^@^@$
    >
    > The Fortran people can help you fix that (unless you do want this
    > odd behaviour).
    >
    > <snip>
    >> char *
    >> testc (void)
    >> {
    >> size_t size = 50;
    >> char *p = malloc_or_bust (size);
    >> strncpy (p, "this sentence is less than fifty bytes", size - 1);
    >> p[size - 1] = '\0

    >
    > '; is missing here.
    >
    >> return p;
    >> }

    >



    I don't know how I missed on all of that.

    $ gcc -c -Wall -Wextra cfunc7.c -o cfunc.o
    $ gfortran -c -Wall -Wextra caller3.f03 -o caller.o
    $ gfortran -Wall -Wextra caller.o cfunc.o -o out
    $ ./out
    this sentence is less than fifty bytes
    $ cat caller3.f03
    program test
    use iso_c_binding
    implicit none
    interface
    function testc() bind(c) result(pa)
    use iso_c_binding
    type(c_ptr):: pa
    end function testc
    end interface
    type(c_ptr), target :: pa
    character(1, c_char),pointer::fpa:))
    pa = testc()
    call c_f_pointer(pa, fpa, [50])
    print*, fpa(1:50)
    end program test
    ! gfortran -c -Wall -Wextra caller3.f03 -o caller.o
    ! gfortran -Wall -Wextra caller.o cfunc.o -o out
    $ cat cfunc7.c
    #include <stdio.h>
    #include <limits.h>
    #include <stdlib.h>
    #include <string.h>
    char *
    malloc_or_bust (size_t sz)
    {
    char *p = malloc (sz);
    if (p == NULL)
    {
    fprintf (stderr, "malloc failed.\n");
    exit (EXIT_FAILURE);
    }
    return p;
    }
    char *
    testc (void)
    {
    size_t size = 50;
    char *p = malloc_or_bust (size);
    strncpy (p, "this sentence is less than fifty bytes", size - 1);
    p[size - 1] = '\0';
    return p;
    }
    // gcc -c -Wall -Wextra cfunc7.c -o cfunc.o
    $

    It might throw C people off to see the initial space of list-directed
    fortran output, like it did me. Without a format specifier, fortran
    generates the space for historic reasons.
    --
    Uno
     
    Uno, Aug 1, 2011
    #15
  16. Uno <> writes:

    > On 08/01/2011 07:27 AM, Ben Bacarisse wrote:
    >> Uno<> writes:
    >>
    >>> On 07/30/2011 05:23 AM, Ben Bacarisse wrote:
    >>>
    >>>> It's almost always the calling function that determines how you must
    >>>> interface with the called language. This applies to best practice as
    >>>> much as it does to those things that are required.

    >>
    >> I made a mistake. I meant to say "the calling language" not "the
    >> calling function". The point being you need to ask Fortran people about
    >> the best practice.

    >
    > They either don't know or don't want to share.


    Odd. I saw lots of helpful answers to your questions there. What I did
    not see was the question you asked here that I suggested you ask there.
    The only unanswered post I saw was when you posted about C over there;
    and that post did not include a question so it's hard to see how it
    could have been answered even if it had been taken to be on-topic.

    >>> Ok. Fortran is expecting a c-style pointer to a char. This little
    >>> snippet gives you a feel for it. This is pretty-new syntax, and what
    >>> makes it relevant to c is that fortran said *all* interop is with ISO
    >>> C.

    >>
    >> The C has been discussed and you've decided not to use ISO C for some
    >> reason so what more is there to say here? To get an answer to your
    >> question about best practice you need to ask Fortran people, not C
    >> people. Make sure you tell them what you are trying to do because the
    >> Fortran code you have looks wrong to me.

    >
    > How do you figure that I'm not using iso C?


    Your compile lines don't ask for ISO C. You are therefore getting gnu C
    which is something not entirely unlike ISO C but is not ISO C. I doubt
    it matters since the code you wrote is ISO C, but you are then assuming
    that you won't make any changes that will take you away from ISO C and
    that compiling as gnu C does not do anything that messes up the Fortran
    to C calling.

    > Is this a criticism of
    > the fortran part, the C part, or the lack of critical distinction
    > between the two?
    >>
    >>> type(c_ptr):: pa
    >>> end function testc
    >>> end interface
    >>> type(c_ptr), target :: pa
    >>> character(1, c_char),pointer::fpa:))
    >>> pa = testc()
    >>>
    >>> ...
    >>>
    >>> Yes the horror of not seeing semicolons, but again I put the fortran
    >>> stuff at the top, so it can disappear with a reasonable edit.
    >>>
    >>> On the C side, I think I've got something that works well, but I don't
    >>> know that without some code review. This is what dinkumware has for
    >>> strncpy; does anyone have a mnemonic for what the 'n' might mean?

    >>
    >> What do you mean "might mean"? You know what it means because you quote
    >> the documentation:

    >
    > N: null, not null, not null newline....


    I would not bother with a mnemonic. Any mnemonic is likely to lead you
    astray since the 'n' in strncpy is very subtly different from the 'n'
    in, say, strncat. Just get into the habit of having the documentation
    handy (it's just a keystroke away in my editor).

    <snip>
    > It might throw C people off to see the initial space of list-directed
    > fortran output, like it did me. Without a format specifier, fortran
    > generates the space for historic reasons.


    I happen to know some Fortran so that did not bother me. I asked about
    the trailing '.' in your sample output. That is very much more
    suspicious.

    --
    Ben.
     
    Ben Bacarisse, Aug 1, 2011
    #16
  17. Nick Keighley

    Ike Naar Guest

    On 2011-08-01, Uno <> wrote:
    > $ gcc -c -Wall -Wextra cfunc7.c -o cfunc.o
    > $ gfortran -c -Wall -Wextra caller2.f03 -o caller.o
    > $ gfortran -Wall -Wextra caller.o testc.o -o out
    > $ ./out
    > this sentence is less than fifty bytes.


    It looks like you are not running the code generated from cfunc7.c .
    What is testc.o ?
     
    Ike Naar, Aug 1, 2011
    #17
    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. Mano kumar
    Replies:
    2
    Views:
    359
    Kevin Spencer
    Oct 17, 2003
  2. Replies:
    10
    Views:
    1,342
    Malte
    Jun 30, 2005
  3. Replies:
    5
    Views:
    508
  4. John Gordon
    Replies:
    70
    Views:
    1,370
    J. J. Farrell
    Aug 14, 2011
  5. Barry Schwarz

    Re: is there anything unstandard in the c part here

    Barry Schwarz, Jul 26, 2011, in forum: C Programming
    Replies:
    11
    Views:
    403
    Nobody
    Jul 27, 2011
Loading...

Share This Page