memcat fn

Discussion in 'C Programming' started by aarklon@gmail.com, Nov 23, 2007.

  1. Guest

    Hi all,

    is it possible to write a function named memcat, which offers
    functionality similar to that of the strcat fn, i.e i mean a function
    on the following lines:-

    void * memcat(void *s1, void *s2);

    now s1 should point to the beginning of the concatenated memory
    region. now as in strcat how to determine the terminating memory
    location...???
     
    , Nov 23, 2007
    #1
    1. Advertising

  2. Mark Bluemel Guest

    wrote:
    > Hi all,
    >
    > is it possible to write a function named memcat, which offers
    > functionality similar to that of the strcat fn, i.e i mean a function
    > on the following lines:-
    >
    > void * memcat(void *s1, void *s2);


    You need to define the functionality you expect from such a function.

    > now s1 should point to the beginning of the concatenated memory
    > region. now as in strcat how to determine the terminating memory
    > location...???


    That, as the man said so memorably, is the question.
     
    Mark Bluemel, Nov 23, 2007
    #2
    1. Advertising

  3. Eric Sosman Guest

    wrote:
    > Hi all,
    >
    > is it possible to write a function named memcat, which offers
    > functionality similar to that of the strcat fn, i.e i mean a function
    > on the following lines:-
    >
    > void * memcat(void *s1, void *s2);
    >
    > now s1 should point to the beginning of the concatenated memory
    > region. now as in strcat how to determine the terminating memory
    > location...???


    Let's begin with the last question: How to determine
    the end. Two ends, really, because you need to find the
    end of the existing piece that begins at s1 and the end
    of the added piece that begins at s2. The other memxxx
    function (memset, memchr, ...) use byte counts for this:
    the caller provides an extra argument giving the number
    of bytes in the memory area. For memcat there are two
    memory areas, hence two counts, and the function looks like

    void *memcat(void *s1, size_t n1, void *s2, size_t n2);

    Let's not stop there, though. Think for a minute about
    what memcat will do, internally. All the area 1 bytes will
    remain as they are, untouched, and the new material will be
    added right after them. So memcat probably begins with

    void *target = (char*)s1 + n1;

    .... to get a pointer the the spot where the new material
    will go. (The (char*) cast is needed because you can't do
    arithmetic on a void* pointer.) What next? The rest of the
    job is just copying the area 2 material to its new position.
    So the complete implementation of memcat might look like

    void *memcat(void *s1, size_t n1, void *s2, size_t n2) {
    void *target = (char*)s1 + n1;
    memcpy(target, s2, n2);
    return s1;
    }

    .... or, with some abbreviation
    void *memcat(void *s1, size_t n1, void *s2, size_t n2) {
    memcpy((char*)s1 + n1, s2, n2);
    return s1;
    }

    (An "industrial-strength" version would probably use const
    on s2, and a version for C99 compilers would also use the
    restrict qualifier, but the outline would be the same.)

    In other words, memcat is just memcpy with a different
    starting point! And that's probably why it doesn't exist in
    the Standard library: it's a trivial variation on a function
    that's already provided. Adding it would be a little bit like
    adding a sqrt_half function that computed the square root of
    one-half its argument: A task that's easily done by calling
    the usual sqrt function with a halved argument to begin with.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Nov 23, 2007
    #3
  4. On Fri, 23 Nov 2007 09:10:52 -0500,
    Eric Sosman <> wrote:
    > wrote:
    >> Hi all,
    >>
    >> is it possible to write a function named memcat, which offers
    >> functionality similar to that of the strcat fn, i.e i mean a function
    >> on the following lines:-
    >>
    >> void * memcat(void *s1, void *s2);
    >>
    >> now s1 should point to the beginning of the concatenated memory
    >> region. now as in strcat how to determine the terminating memory
    >> location...???


    [snip]
    >
    > void *memcat(void *s1, size_t n1, void *s2, size_t n2) {
    > memcpy((char*)s1 + n1, s2, n2);
    > return s1;
    > }


    of course, if you wrote it like this, you'd have to include string.h, in
    which case you shouldn't be naming your function memcat()i as long as it
    has external linkage, as that would be a reserved identifier.

    Martien
    --
    |
    Martien Verbruggen | Computers in the future may weigh no more
    | than 1.5 tons. -- Popular Mechanics, 1949
    |
     
    Martien Verbruggen, Nov 23, 2007
    #4
  5. On Sat, 24 Nov 2007 08:43:57 +1100, Martien Verbruggen wrote:
    > On Fri, 23 Nov 2007 09:10:52 -0500,
    > Eric Sosman <> wrote:
    >>
    >> void *memcat(void *s1, size_t n1, void *s2, size_t n2) {
    >> memcpy((char*)s1 + n1, s2, n2);
    >> return s1;
    >> }

    >
    > of course, if you wrote it like this, you'd have to include string.h, in
    > which case you shouldn't be naming your function memcat()i as long as it
    > has external linkage, as that would be a reserved identifier.


    memcat is a reserved external name even if you don't include string.h.
    Including string.h means that you're also not allowed to define static
    void *memcat(...), or typedef void memcat, since it becomes reserved as a
    file scope identifier.
     
    Harald van Dij殺俎k, Nov 23, 2007
    #5
  6. CBFalconer Guest

    wrote:
    >
    > is it possible to write a function named memcat, which offers
    > functionality similar to that of the strcat fn, i.e i mean a
    > function on the following lines:-
    >
    > void * memcat(void *s1, void *s2);
    >
    > now s1 should point to the beginning of the concatenated memory
    > region. now as in strcat how to determine the terminating memory
    > location...???


    Strings are terminated by the final '\0'. Memory blocks have no
    such delimiter. Thus you have to have, and supply, the sizes of
    the memory blocks. Therefore the prototype could be:

    int memcat(char *s1, size_t sz1, /* input block & destination
    */
    char *s2, size_t sz2, /* block to add to it */
    size_t szout); /* maximum size of *s1 */

    and it can return an error indicator, such as non-zero for failure
    to fit everything.

    --
    Chuck F (cbfalconer at maineline dot net)
    <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Nov 23, 2007
    #6
  7. Guest

    On Nov 23, 4:43 pm, Martien Verbruggen <>
    wrote:
    > On Fri, 23 Nov 2007 09:10:52 -0500,
    > Eric Sosman <> wrote:
    >
    > > wrote:
    > >> Hi all,

    >
    > >> is it possible to write a function named memcat, which offers
    > >> functionality similar to that of the strcat fn, i.e i mean a function
    > >> on the following lines:-

    >
    > >> void * memcat(void *s1, void *s2);

    >
    > >> now s1 should point to the beginning of the concatenated memory
    > >> region. now as in strcat how to determine the terminating memory
    > >> location...???

    >
    > [snip]
    >
    >
    >
    > > void *memcat(void *s1, size_t n1, void *s2, size_t n2) {
    > > memcpy((char*)s1 + n1, s2, n2);
    > > return s1;
    > > }

    >
    > of course, if you wrote it like this, you'd have to include string.h, in
    > which case you shouldn't be naming your function memcat()i as long as it
    > has external linkage, as that would be a reserved identifier.
    >
    > Martien
    > --
    > |
    > Martien Verbruggen | Computers in the future may weigh no more
    > | than 1.5 tons. -- Popular Mechanics, 1949
    > |


    I searched my /usr/include/string.h file for memcat but i didn't find
    any. I use gcc v 4.01
     
    , Nov 24, 2007
    #7
  8. Flash Gordon Guest

    wrote, On 24/11/07 04:13:
    > On Nov 23, 4:43 pm, Martien Verbruggen <>
    > wrote:


    <snip>

    >> of course, if you wrote it like this, you'd have to include string.h, in
    >> which case you shouldn't be naming your function memcat()i as long as it
    >> has external linkage, as that would be a reserved identifier.
    >>
    >> Martien
    >> --
    >> |
    >> Martien Verbruggen | Computers in the future may weigh no more
    >> | than 1.5 tons. -- Popular Mechanics, 1949
    >> |


    Please don't quote peoples signatures, the bit typically after the "-- "
    or anything else not relevant to your reply.

    > I searched my /usr/include/string.h file for memcat but i didn't find
    > any. I use gcc v 4.01


    Martien did not say it was defined, he said it was reserved. I.e. you
    are *not* allowed to use that name whether it is currently used or not.
    The GNU people could decide to use it in the next minor release thus
    breaking your code, or they might be using some "compiler magic" which
    well break your code, or they could perfectly legally just detect that
    you have used it and deliberately generate code that generates random
    insults.
    --
    Flash Gordon
     
    Flash Gordon, Nov 24, 2007
    #8
  9. On Fri, 23 Nov 2007 20:13:33 -0800 (PST), wrote:

    >On Nov 23, 4:43 pm, Martien Verbruggen <>
    >wrote:


    snip

    >> of course, if you wrote it like this, you'd have to include string.h, in
    >> which case you shouldn't be naming your function memcat()i as long as it
    >> has external linkage, as that would be a reserved identifier.
    >>
    >> Martien
    >> --
    >> |
    >> Martien Verbruggen | Computers in the future may weigh no more
    >> | than 1.5 tons. -- Popular Mechanics, 1949
    >> |

    >
    >I searched my /usr/include/string.h file for memcat but i didn't find
    >any. I use gcc v 4.01


    Which only proves that your system doesn't have it.

    The real issue is that the name is reserved, regardless of whether it
    is in use at the moment or not.


    Remove del for email
     
    Barry Schwarz, Nov 25, 2007
    #9
  10. Guest

    On Nov 23, 9:10 am, Eric Sosman <> wrote:
    > wrote:
    > > Hi all,

    >
    > > is it possible to write a function named memcat, which offers
    > > functionality similar to that of the strcat fn, i.e i mean a function
    > > on the following lines:-

    >
    > > void * memcat(void *s1, void *s2);

    >
    > > now s1 should point to the beginning of the concatenated memory
    > > region. now as in strcat how to determine the terminating memory
    > > location...???

    >
    > Let's begin with the last question: How to determine
    > the end. Two ends, really, because you need to find the
    > end of the existing piece that begins at s1 and the end
    > of the added piece that begins at s2. The other memxxx
    > function (memset, memchr, ...) use byte counts for this:
    > the caller provides an extra argument giving the number
    > of bytes in the memory area. For memcat there are two
    > memory areas, hence two counts, and the function looks like
    >
    > void *memcat(void *s1, size_t n1, void *s2, size_t n2);
    >
    > Let's not stop there, though. Think for a minute about
    > what memcat will do, internally. All the area 1 bytes will
    > remain as they are, untouched, and the new material will be
    > added right after them. So memcat probably begins with
    >
    > void *target = (char*)s1 + n1;
    >
    > ... to get a pointer the the spot where the new material
    > will go. (The (char*) cast is needed because you can't do
    > arithmetic on a void* pointer.) What next? The rest of the
    > job is just copying the area 2 material to its new position.
    > So the complete implementation of memcat might look like
    >
    > void *memcat(void *s1, size_t n1, void *s2, size_t n2) {
    > void *target = (char*)s1 + n1;
    > memcpy(target, s2, n2);
    > return s1;
    > }
    >
    > ... or, with some abbreviation
    > void *memcat(void *s1, size_t n1, void *s2, size_t n2) {
    > memcpy((char*)s1 + n1, s2, n2);
    > return s1;
    > }
    >
    > (An "industrial-strength" version would probably use const
    > on s2, and a version for C99 compilers would also use the
    > restrict qualifier, but the outline would be the same.)
    >
    > In other words, memcat is just memcpy with a different
    > starting point! And that's probably why it doesn't exist in
    > the Standard library: it's a trivial variation on a function
    > that's already provided. Adding it would be a little bit like
    > adding a sqrt_half function that computed the square root of
    > one-half its argument: A task that's easily done by calling
    > the usual sqrt function with a halved argument to begin with.


    I tried your function as follows:-

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

    void *mcat(void *s1, size_t n1, void *s2, size_t n2)
    {
    int k;
    void *target = (char*)s1 + n1;
    memcpy(target,s2, n2);

    return s1;
    }

    int main(void)
    {

    int i =2,j=3,k;
    int *p,*q,*r;

    p = &i; q = &j;
    r = mcat(p,sizeof(int),q,sizeof(int));

    for(k=0;k<2;k++)
    printf("\t %d",r[k]);
    puts("");
    return(EXIT_SUCCESS);
    }

    29,1
    but getting the o/p as 2 1 instead of 2 3
     
    , Nov 30, 2007
    #10
  11. Mark Bluemel Guest

    wrote:
    > On Nov 23, 9:10 am, Eric Sosman <> wrote:

    [Snip]
    >
    > I tried your function as follows:-


    Why? Eric pointed out that the function was stupid and unnecessary.

    >
    > #include<stdio.h>
    > #include<stdlib.h>
    > #include<string.h>
    >
    > void *mcat(void *s1, size_t n1, void *s2, size_t n2)
    > {
    > int k;
    > void *target = (char*)s1 + n1;
    > memcpy(target,s2, n2);
    >
    > return s1;
    > }
    >
    > int main(void)
    > {
    >
    > int i =2,j=3,k;
    > int *p,*q,*r;
    >
    > p = &i; q = &j;
    > r = mcat(p,sizeof(int),q,sizeof(int));
    >
    > for(k=0;k<2;k++)
    > printf("\t %d",r[k]);
    > puts("");
    > return(EXIT_SUCCESS);
    > }
    >


    The crucial part of this code boils down to :-

    int i =2,j=3,k;
    void *source = &j;
    void *target = ((char *)&i) + sizeof(int);
    memcpy(target,source,sizeof(int));

    Which could be expanded to

    int i =2,j=3,k;
    char *source = &j;
    char *target = ((char *)&i) + sizeof(int);
    for(k=0;k < sizeof(int);k++) {
    *source++ = *target++;
    }


    Which in turn could be replaced with

    int i =2,j=3,k;
    int *target = &i + 1;
    *target = j;

    What makes you think you can assign to some arbitrary place in memory?
     
    Mark Bluemel, Nov 30, 2007
    #11
  12. Eric Sosman Guest

    Mark Bluemel wrote:
    > wrote:
    >> On Nov 23, 9:10 am, Eric Sosman <> wrote:

    > [Snip]
    >>
    >> I tried your function as follows:-

    >
    > Why? Eric pointed out that the function was stupid and unnecessary.


    No, I did not. I called it "a trivial variation on a
    function that's already provided," but I never said it
    was "stupid." If you have opinions, go ahead and state
    them -- but state them as your own, not as mine.

    Or as Shakespeare put it, "Who steals my parse steals
    trash."

    --
    Eric Sosman
    lid
     
    Eric Sosman, Nov 30, 2007
    #12
  13. Mark Bluemel Guest

    Eric Sosman wrote:
    > Mark Bluemel wrote:
    >> wrote:
    >>> On Nov 23, 9:10 am, Eric Sosman <> wrote:

    >> [Snip]
    >>>
    >>> I tried your function as follows:-

    >>
    >> Why? Eric pointed out that the function was stupid and unnecessary.

    >
    > No, I did not. I called it "a trivial variation on a
    > function that's already provided," but I never said it
    > was "stupid." If you have opinions, go ahead and state
    > them -- but state them as your own, not as mine.


    Sorry about that - I was a little cavalier.
     
    Mark Bluemel, Nov 30, 2007
    #13
  14. On 30 Nov, 03:42, wrote:

    <snip>

    I know others have replied but I'm not sure if you understood
    them

    > I tried your function as follows:-
    >
    > #include<stdio.h>
    > #include<stdlib.h>
    > #include<string.h>
    >
    > void *mcat(void *s1, size_t n1, void *s2, size_t n2)
    > {
    > int k;
    > void *target = (char*)s1 + n1;
    > memcpy(target,s2, n2);
    >
    > return s1;
    > }
    >
    > int main(void)
    > {
    >
    > int i =2,j=3,k;
    > int *p,*q,*r;
    >
    > p = &i; q = &j;
    > r = mcat(p,sizeof(int),q,sizeof(int));


    what is the point of p, q and r?

    why not (ignoring for the moment that it doesn't work...)

    mcat (&i, sizeof(int), &j, sizeof(int));

    note r is uneccessary because j is copied to i + sizeof(int)

    so why won't this work? Becuse you've go no space for the extra
    bytes. Suppose an int is 4 bytes (I like concrete explanations!).
    Thus i has been allocated 4 bytes. And so has has j. The mcat call
    resolves to a memcpy call that tries to add 4 bytes onto the end
    of a 4 byte object! In my country we talk of trying to put a quart
    into a pint pot. (trying to put 1136ml of fluid into 568ml container).
    If i were an array with two entries you might have more luck

    int i[2] = {2, 0}, j = 3;
    mcat (&i[0], sizeof(int), &j, sizeof(int));


    --
    Nick Keighley

    Egon: Don't over run the end of the array
    Venkman: Why?
    Egon: It would be bad.
    Venkman: I'm fuzzy on the whole good-bad thing. Whattya mean "bad?"
    Egon: Try to imagine all life as you know it stopping instantaneously
    and every molecule in your body exploding at the speed of light.
    Ray: Total protonic reversal....
    Venkman: Right, that's bad...OK.. important safety tip. Thanks, Egon.
    (early Undefined Behaviour)
     
    Nick Keighley, Nov 30, 2007
    #14
  15. Guest

    On Nov 30, 11:07 am, Nick Keighley <>
    wrote:
    > On 30 Nov, 03:42, wrote:
    >
    > <snip>
    >
    > I know others have replied but I'm not sure if you understood
    > them
    >
    >
    >
    > > I tried your function as follows:-

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

    >
    > > void *mcat(void *s1, size_t n1, void *s2, size_t n2)
    > > {
    > > int k;
    > > void *target = (char*)s1 + n1;
    > > memcpy(target,s2, n2);

    >
    > > return s1;
    > > }

    >
    > > int main(void)
    > > {

    >
    > > int i =2,j=3,k;
    > > int *p,*q,*r;

    >
    > > p = &i; q = &j;
    > > r = mcat(p,sizeof(int),q,sizeof(int));

    >
    > what is the point of p, q and r?
    >
    > why not (ignoring for the moment that it doesn't work...)
    >
    > mcat (&i, sizeof(int), &j, sizeof(int));
    >
    > note r is uneccessary because j is copied to i + sizeof(int)
    >
    > so why won't this work? Becuse you've go no space for the extra
    > bytes. Suppose an int is 4 bytes (I like concrete explanations!).
    > Thus i has been allocated 4 bytes. And so has has j. The mcat call
    > resolves to a memcpy call that tries to add 4 bytes onto the end
    > of a 4 byte object! In my country we talk of trying to put a quart
    > into a pint pot. (trying to put 1136ml of fluid into 568ml container).
    > If i were an array with two entries you might have more luck
    >
    > int i[2] = {2, 0}, j = 3;
    > mcat (&i[0], sizeof(int), &j, sizeof(int));
    >
    > --


    Okay i tried this:-

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

    void *mcat(void *s1, size_t n1, void *s2, size_t n2)
    {
    int k;
    void *target = (char*)s1 + n1;
    memcpy(target,s2, n2);

    return s1;
    }

    int main(void)
    {
    int i[2] = {2, 0},j = 3;

    printf("\t %d",i[0]);
    printf("\t %d",i[1]);
    printf("\t %d",i[2]);

    mcat (&i[0], sizeof(int), &j, sizeof(int));

    puts("");
    printf("\t %d",i[0]);
    printf("\t %d",i[1]);
    printf("\t %d",i[2]);

    puts("");
    return(EXIT_SUCCESS);
    }
    but getting o/p as follows:-

    2 0 -1208468512
    2 3 -1208468512

    instead of 2 0 3
     
    , Nov 30, 2007
    #15
  16. santosh Guest

    wrote:

    > On Nov 30, 11:07 am, Nick Keighley <>
    > wrote:
    >> On 30 Nov, 03:42, wrote:
    >>
    >> <snip>
    >>
    >> I know others have replied but I'm not sure if you understood
    >> them
    >>
    >>
    >>
    >> > I tried your function as follows:-

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

    >>
    >> > void *mcat(void *s1, size_t n1, void *s2, size_t n2)
    >> > {
    >> > int k;
    >> > void *target = (char*)s1 + n1;
    >> > memcpy(target,s2, n2);

    >>
    >> > return s1;
    >> > }

    >>
    >> > int main(void)
    >> > {

    >>
    >> > int i =2,j=3,k;
    >> > int *p,*q,*r;

    >>
    >> > p = &i; q = &j;
    >> > r = mcat(p,sizeof(int),q,sizeof(int));

    >>
    >> what is the point of p, q and r?
    >>
    >> why not (ignoring for the moment that it doesn't work...)
    >>
    >> mcat (&i, sizeof(int), &j, sizeof(int));
    >>
    >> note r is uneccessary because j is copied to i + sizeof(int)
    >>
    >> so why won't this work? Becuse you've go no space for the extra
    >> bytes. Suppose an int is 4 bytes (I like concrete explanations!).
    >> Thus i has been allocated 4 bytes. And so has has j. The mcat call
    >> resolves to a memcpy call that tries to add 4 bytes onto the end
    >> of a 4 byte object! In my country we talk of trying to put a quart
    >> into a pint pot. (trying to put 1136ml of fluid into 568ml
    >> container). If i were an array with two entries you might have more
    >> luck
    >>
    >> int i[2] = {2, 0}, j = 3;
    >> mcat (&i[0], sizeof(int), &j, sizeof(int));
    >>
    >> --

    >
    > Okay i tried this:-
    >
    > #include<string.h>
    > #include<stdio.h>
    > #include<stdlib.h>
    >
    > void *mcat(void *s1, size_t n1, void *s2, size_t n2)
    > {
    > int k;
    > void *target = (char*)s1 + n1;
    > memcpy(target,s2, n2);
    >
    > return s1;
    > }
    >
    > int main(void)
    > {
    > int i[2] = {2, 0},j = 3;
    >
    > printf("\t %d",i[0]);
    > printf("\t %d",i[1]);
    > printf("\t %d",i[2]);


    The valid range of indexes for the array 'i' are 0 and 1. You can point
    to one past the end of an array, but you cannot deference it. Doing so
    invokes undefined behaviour. So scrap that last printf() call.

    > mcat (&i[0], sizeof(int), &j, sizeof(int));


    Wrong. The size of the array can be got by:

    sizeof i

    in this function. Passing it to another function causes it to "drop"
    it's size information and sizeof will no longer work as above. It will
    instead yield the size of the pointer to such an array. Therefore you
    need to manually pass the size information.

    Also 'i' needs to be at least one element larger to accomodate 'j' being
    copied over.

    > puts("");
    > printf("\t %d",i[0]);
    > printf("\t %d",i[1]);
    > printf("\t %d",i[2]);
    >
    > puts("");
    > return(EXIT_SUCCESS);
    > }
    > but getting o/p as follows:-
    >
    > 2 0 -1208468512
    > 2 3 -1208468512
    >
    > instead of 2 0 3


    Make 'i' have three elements.
     
    santosh, Nov 30, 2007
    #16
  17. Guest


    >Make 'i' have three elements.


    then whats the point in trying a mcat/memcat function ????.....
     
    , Nov 30, 2007
    #17
  18. santosh Guest

    wrote:
    > santosh wrote:
    >> wrote:


    *Please* include context in your posts. I have added it in this
    instance.

    >>> Okay i tried this:-
    >>>
    >>> #include<string.h>
    >>> #include<stdio.h>
    >>> #include<stdlib.h>
    >>>
    >>> void *mcat(void *s1, size_t n1, void *s2, size_t n2)
    >>> {
    >>> int k;
    >>> void *target = (char*)s1 + n1;
    >>> memcpy(target,s2, n2);
    >>>
    >>> return s1;
    >>> }
    >>>
    >>> int main(void)
    >>> {
    >>> int i[2] = {2, 0},j = 3;
    >>>
    >>> printf("\t %d",i[0]);
    >>> printf("\t %d",i[1]);
    >>> printf("\t %d",i[2]);


    >> The valid range of indexes for the array 'i' are 0 and 1. You can
    >> point to one past the end of an array, but you cannot deference it.
    >> Doing so invokes undefined behaviour. So scrap that last printf()
    >> call.


    >>> mcat (&i[0], sizeof(int), &j, sizeof(int));


    >> Wrong. The size of the array can be got by:
    >>
    >> sizeof i
    >>
    >> in this function. Passing it to another function causes it to "drop"
    >> it's size information and sizeof will no longer work as above. It
    >> will instead yield the size of the pointer to such an array.
    >> Therefore you need to manually pass the size information.


    >> Also 'i' needs to be at least one element larger to accomodate 'j'
    >> being copied over.


    >>> puts("");
    >>> printf("\t %d",i[0]);
    >>> printf("\t %d",i[1]);
    >>> printf("\t %d",i[2]);
    >>>
    >>> puts("");
    >>> return(EXIT_SUCCESS);
    >>> }
    >>> but getting o/p as follows:-
    >>>
    >>> 2 0 -1208468512
    >>> 2 3 -1208468512
    >>>
    >>> instead of 2 0 3


    >> Make 'i' have three elements.

    >
    > then whats the point in trying a mcat/memcat function ????.....


    Point? That's something that you should know when you designed the
    function. Mcat() as you have written it above expects the array at 's1'
    to be "big enough" to attach the array starting at 's2' to it. If it is
    not, then that constitutes a violation of contract by the caller and
    results in a buffer overrun and consequent Undefined behaviour.

    If you want the mcat() function to handle this situation then you need
    to know the size of the array at 's1', not merely the offset at which
    you are doing the concatenation. Then if the size is insufficient for a
    straight copy, you need to dynamically enlarge the array using
    realloc() before proceeding. This of course requires the original array
    to be allocated with a previous call to *alloc(). Trying to resize a
    static array is an error. This complicates the interface and usage of
    the function significantly.

    Actually your mcat() function as it stands can be completely replaced by
    a single call to memcpy() or memmove(). So you might look into making
    it handle undersized arguments to actually make it useful.
     
    santosh, Nov 30, 2007
    #18
  19. On Fri, 30 Nov 2007 11:07:10 -0800 (PST), wrote:


    snip - It helps if you trim obsolete code from your posts.

    >Okay i tried this:-
    >
    > #include<string.h>
    > #include<stdio.h>
    > #include<stdlib.h>
    >
    > void *mcat(void *s1, size_t n1, void *s2, size_t n2)
    > {
    > int k;
    > void *target = (char*)s1 + n1;
    > memcpy(target,s2, n2);
    >
    > return s1;
    > }
    >
    > int main(void)
    > {
    > int i[2] = {2, 0},j = 3;


    How many elements in the array i? What are their indices?

    >
    > printf("\t %d",i[0]);
    > printf("\t %d",i[1]);
    > printf("\t %d",i[2]);


    Do you really think i[2] exists? If you want to see a 3 in your
    output, then print j.

    >
    > mcat (&i[0], sizeof(int), &j, sizeof(int));
    >
    > puts("");
    > printf("\t %d",i[0]);
    > printf("\t %d",i[1]);
    > printf("\t %d",i[2]);
    >
    > puts("");
    > return(EXIT_SUCCESS);
    > }
    >but getting o/p as follows:-
    >
    > 2 0 -1208468512
    > 2 3 -1208468512
    >
    >instead of 2 0 3


    Do you have any reason to believe that j follows i in memory?


    Remove del for email
     
    Barry Schwarz, Dec 4, 2007
    #19
  20. Kaz Kylheku Guest

    On Nov 29, 7:42 pm, wrote:
    > void *mcat(void *s1, size_t n1, void *s2, size_t n2)
    > {
    > int k;


    Unused variable.

    > void *target = (char*)s1 + n1;
    > memcpy(target,s2, n2);
    >
    > return s1;
    > }


    This is just a flavor of memcpy where the destination is specified as
    an address with displacement. In other words, it's just the memcpy
    ``instruction'' with a different ``addressing mode'' for the
    destination operand! :)

    How about indirect with scaled index and displacement, hahaha:

    void *mcpy_ind_scidx_disp(void *base, size_t index, size_t scale,
    size_t disp,
    void *source, size_t size)
    {
    void *effective_addr = (char *) base + index * scale + disp;
    return memcpy(effective_addr, source, size);
    /* returning effective_addr is probably more useful than base or
    source */
    }

    I hope you realize that the effective address calculation for the
    addressing mode can be decoupled from the operation itself. That is to
    say, we can separate the part which does the addressing mode into its
    own function, and then just pass the resulting direct address to
    regular memcpy.

    void *ind_scidx_disp(void *base, size_t index, size_t scale)
    {
    return (char *) base + index * scale + disp;
    }

    Now instead of

    mcpy_ind_scidx_disp(x, y, z, d, s);

    you write:

    memcpy(ind_scidx_disp(x, y, z), d, s);

    and as a bonus, you can reuse the addressing mode calculation with
    memset, memmove, and memchr.

    It's exactly two characters extra to type, which is due to the extra
    level of parentheses.
     
    Kaz Kylheku, Dec 4, 2007
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page