string1=string2 changes value of string2 if I change string1

Discussion in 'C Programming' started by Rudra Banerjee, Sep 15, 2012.

  1. Dear friends,
    I have a function,

    static void mk_bib(GtkWidget *widget, gpointer data) {
    if (!filename) {
    caution("No File Selected");
    } else {
    char *bibstyl = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(bibcombo));
    if (strcmp(bibstyl, "==select bibstyle==") == 0) {
    caution("Select Bibliography style file");
    } else {
    char *p1 = filename;
    char *p2 = rindex(p1, '.');
    if (p2 != NULL) {
    if (strcmp(p2, ".bib") == 0) {
    *p2 = '\0';
    }
    }
    g_print("Before basefn=Bibstyl=>%s\n",bibstyl);
    char *basefn=bibstyl;
    strcat(basefn, ".tex");
    g_print("Before basefn=Bibstyl=>%s\n",bibstyl);
    }
    }
    }

    which, while running, changes value of bibstyl after strcat.
    the result of two g_print is:

    Before basefn=Bibstyl=>aabbrv
    Before basefn=Bibstyl=>aabbrv.tex

    Why it is so? Where I am doing wrong?
     
    Rudra Banerjee, Sep 15, 2012
    #1
    1. Advertising

  2. Rudra Banerjee wrote:
    >
    > Why it is so? Where I am doing wrong?


    > char *basefn=bibstyl;

    you copied the pointer, not the string. They both(basefn and bibstyl)
    point at the same string. Use strndup or something similar.
     
    Johann Klammer, Sep 15, 2012
    #2
    1. Advertising

  3. In article <>,
    Rudra Banerjee <> wrote:
    ....

    Kiki will tell you any second now that C has no "string" data type.

    Instead, it merely has (char) pointers, which most people treat as if they
    were a string type, but in fact, they are not.

    Once you understand this, it will become obvious why your program does what
    it does.

    --
    "Remember when teachers, public employees, Planned Parenthood, NPR and PBS
    crashed the stock market, wiped out half of our 401Ks, took trillions in
    TARP money, spilled oil in the Gulf of Mexico, gave themselves billions in
    bonuses, and paid no taxes? Yeah, me neither."
     
    Kenny McCormack, Sep 15, 2012
    #3
  4. Rudra Banerjee

    James Kuyper Guest

    On 09/15/2012 09:59 AM, Rudra Banerjee wrote:
    > Dear friends,
    > I have a function,
    >
    > static void mk_bib(GtkWidget *widget, gpointer data) {
    > if (!filename) {
    > caution("No File Selected");
    > } else {
    > char *bibstyl = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(bibcombo));
    > if (strcmp(bibstyl, "==select bibstyle==") == 0) {
    > caution("Select Bibliography style file");
    > } else {
    > char *p1 = filename;
    > char *p2 = rindex(p1, '.');
    > if (p2 != NULL) {
    > if (strcmp(p2, ".bib") == 0) {
    > *p2 = '\0';
    > }
    > }
    > g_print("Before basefn=Bibstyl=>%s\n",bibstyl);
    > char *basefn=bibstyl;
    > strcat(basefn, ".tex");
    > g_print("Before basefn=Bibstyl=>%s\n",bibstyl);
    > }
    > }
    > }
    >
    > which, while running, changes value of bibstyl after strcat.
    > the result of two g_print is:
    >
    > Before basefn=Bibstyl=>aabbrv
    > Before basefn=Bibstyl=>aabbrv.tex
    >
    > Why it is so?


    Because you set basefn to point at the same place that bibstyle points
    at, and then passed that pointer value to strcat(). You told strcat()
    to put it's output there. If you wanted it to put the output somewhere
    else, you should have reserved some memory to put it into.

    You have five basic choices, depending upon how long you want the memory
    to last, and other issues. I'll demonstrate all five:

    // You're responsible for setting ENOUGH_SPACE big enough.
    #define ENOUGH_SPACE 128
    char file_scope_static[ENOUGH_SPACE];

    static void mk_bib(GtkWidget *widget, gpointer data)
    {
    static char block_scope_static[ENOUGH_SPACE];
    char automatic[ENOUGH_SPACE];

    // other code
    {
    // VLAs are only guaranteed to be supported in C99. They didn't
    // exist in C90, and have been made optional in C2011.
    char vla[strlen(bibstyle)+sizeof ".tex"];
    char *dynamic = malloc(strlen(bibstyle)+sizeof ".tex");
    if(dynamic)
    {
    char *basefn;
    // At this point, you can set basefn to point a
    // file_scope_static, block_scope_static, automatic, vla,
    // or dynamic. Your choice.
    #ifdef YOUR_WAY
    strcpy(basefn, bibstyle);
    strcat(basefn, ".tex");
    #else // MY_WAY
    sprintf(base fn, "%s.tex", bibstyle);
    #endif
    free(dynamic);
    }
    else
    {
    // out of memory error handling
    }
    }
    }

    Memory will be allocated for file_scope_static and block_scope_static
    for the entire lifetime of your program.
    Memory will be allocated for automatic and vla only during the lifetime
    of the code block that they are defined in.
    The memory pointed at by dynamic will remain allocated until you call
    free(). If you never call free(), it will remain allocated until the
    very end of your program, even after the variable named "dynamic" no
    longer exists. This is called a memory leak, and should normally be
    avoided - but there are situations where it's harmless, or at least
    fairly well justified.

    Which of these methods is appropriate depends upon how long you need the
    memory to remain allocated. For your example code, I'd normally go with
    automatic, but your actual code might need to hold onto the memory a
    little longer than that.
    --
    James Kuyper
     
    James Kuyper, Sep 15, 2012
    #4
  5. Johann Klammer <1.net> writes:
    > Rudra Banerjee wrote:
    >> Why it is so? Where I am doing wrong?

    >
    > > char *basefn=bibstyl;

    > you copied the pointer, not the string. They both(basefn and bibstyl)
    > point at the same string. Use strndup or something similar.


    strndup() is a "safer" version of strdup(). Both strndup()
    and strdup() are non-standard, so using either will limit the
    portability of your code.

    The usual way to copy the contents of a string, rather
    than copying a pointer to it, is the strcpy() function --
    but it won't allocate memory for you, nor will it check
    that there's enough room in the target array. (strncpy()
    is *not* a safer verison of strcpy(); it's a very different
    function that's rarely useful. I've written about it at
    <http://the-flat-trantor-society.blogspot.com/2012/03/no-strncpy-is-not-safer-strcpy.html>.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Sep 15, 2012
    #5
  6. Rudra Banerjee

    Kaz Kylheku Guest

    On 2012-09-15, Keith Thompson <> wrote:
    > Johann Klammer <1.net> writes:
    >> Rudra Banerjee wrote:
    >>> Why it is so? Where I am doing wrong?

    >>
    >> > char *basefn=bibstyl;

    >> you copied the pointer, not the string. They both(basefn and bibstyl)
    >> point at the same string. Use strndup or something similar.

    >
    > strndup() is a "safer" version of strdup(). Both strndup()
    > and strdup() are non-standard, so using either will limit the
    > portability of your code.


    That's nonsense. What limits the portability of code is what is actually
    implemented, not what is standard.

    The standard is just a pile of paper. Moreover, the latest few revisiosn of it
    describe an imaginary language that is not completely implemented anywhere.
    Thus, some non-standard things are actually more widely portable than
    some standard ones. For example, strdup will work on Unix-like systems and
    Microsoft Visual C, whereas some "standard" C99 features will not.

    You can easily use preprocessor symbols to capture a configuration, which
    informs your program about what functions are not available and have
    to be reimplemented locally:

    /* header */
    #if !HAVE_STRNDUP
    extern char *strdup(const char *); /* your own declaration */
    #endif

    /* C file */
    #if !HAVE_STRNDUP
    char *strdup(const char *in)
    {
    /* your own implementation */
    }
    #endif

    See, now it's portable.
     
    Kaz Kylheku, Sep 15, 2012
    #6
    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. =?Utf-8?B?d2lsbGlhbQ==?=
    Replies:
    3
    Views:
    2,769
    =?Utf-8?B?d2lsbGlhbQ==?=
    Jan 28, 2005
  2. crjunk
    Replies:
    3
    Views:
    464
    crjunk
    Oct 31, 2008
  3. asil klin
    Replies:
    28
    Views:
    1,328
    Andreas Leitgeb
    Mar 5, 2011
  4. giri alamuri
    Replies:
    5
    Views:
    179
    giri alamuri
    Sep 12, 2003
  5. Replies:
    6
    Views:
    223
Loading...

Share This Page