Link to home
Start Free TrialLog in
Avatar of bot403
bot403

asked on

Newbie Q: Modifying string passed by reference.

I know the test code is messy but it illustrates my concept. I would like to know why
this very simple  test program outputs:
test
test

instead of what i would expect:
test
modifed

here is the code.

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
int main();
int modify(char *p);
int main(){
        char *p = "test";
        puts(p);
        modify(p);
        puts(p);
}

int modify(char *p){
        p = malloc(sizeof(char) * 20);
        strcpy(p,"modified");
}

I am sure I am missing some simple concept...but can anyone explain what that
concept is? I have a few thick books on C and cannot deduce what the problem
would be. The code below SHOULD be of the same concept and it produces the
expected result. It's output is
1
2

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

int main();
int modify(int *p);

int main(){
        int *p;
        p = malloc(sizeof(int));
        *p = 1;
        printf("%d\n",*p);
        modify(p);
        printf("%d\n",*p);
}

int modify(int *p){
        free(p);
        p = malloc(sizeof(int));
        *p = 2;
}
ASKER CERTIFIED SOLUTION
Avatar of grg99
grg99

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of GaryFx
GaryFx

Ah, yes, I remember the way early FORTRAN compilers did it:

        SUBROUTINE X(I)
        I = 7
        RETURN
        END

        J = 2 *3
10    FORMAT (I5)
        TYPE 10, J
C      This will print 6
        X(3)
        J = 4 * 3
        TYPE 10, J
C      This will print 28, not 12, because the call by address to X changed the
C      value of the constant 3 to be 7
        END

Yes, this really happened on some FORTRAN implementations.  I'm sure bazillions of hours have been spent dealing with this problem.

C++ supports references as a first class concept, which seems right.  And there are good reasons why C only does call by value.  

Gary
The following code would print

test
modified

You have to be careful what memory location you are actually writing to.  As said before by calling malloc, you change the value of p, and thus it points to another string.  Even without calling a function, calling malloc will change the value of the pointer it allocates memory for.  realloc, on the other hand, maintains the original value of the pointer, it just allocates it more memory.

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

void modify(char *);

main()
{
      char *p;
      if ((p = malloc(5)) == NULL)  
            return -1;

      strcpy(p, "test");
      
      puts(p);
      modify(p);
      puts(p);

      return 0;
}

void modify(char *p)
{
      if (realloc(p, 20) == NULL)  
            return;
      strcpy(p, "modified");
}
The following code would print

test
modified

You have to be careful what memory location you are actually writing to.  As said before by calling malloc, you change the value of p, and thus it points to another string.  Even without calling a function, calling malloc will change the value of the pointer it allocates memory for.  realloc, on the other hand, maintains the original value of the pointer, it just allocates it more memory.

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

void modify(char *);

main()
{
      char *p;
      if ((p = malloc(5)) == NULL)  
            return -1;

      strcpy(p, "test");
      
      puts(p);
      modify(p);
      puts(p);

      return 0;
}

void modify(char *p)
{
      if (realloc(p, 20) == NULL)  
            return;
      strcpy(p, "modified");
}
>       TYPE 10, J
>C      This will print 28, not 12, because the call by address to X changed the
>C      value of the constant 3 to be 7
>      END
>
>Yes, this really happened on some FORTRAN implementations.  I'm sure bazillions of hours have been spent dealing with this problem.

I doubt if anybody is really intersted in starting a Language-fight here, but here goes:

True, but 2 out of the 4 main FORTRAN compilers I used back then would print out "ARGUMENT 1 IS CONSTANT MODIFIED IN XXX LINE YY"
I've never seen a C compiler that did this, and with string constants ALWAYS passed by address, it's a IMHO bigger problem
in C than in FORTRAN.

>C++ supports references as a first class concept, which seems right.  And there are good reasons why C only does call by value.  

Opinions may vary, but I don't consider C++ worth the time to argue about. And if there ever were good reasons for C's parameter
passing scheme, they may have been valid on a 56KW PDP-11/20, I doubt if the same holds true today.

Regards,

George
 

Gary