Thread: Manipulating a passed pointer inside a function.

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    4

    Manipulating a passed pointer inside a function.

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    /* scpy1() copies string to a same size char array. */
    void scpy1(char d[], const char s[]);
    
    /* scpy2() tries to allocate memory to d[] inside the body. */
    void scpy2(char d[], const char s[]);
    
    void main()
    {
    	char a[] = "This is a line of ASCII string";
    	char* b = 0;
    	char* c = 0;
    
    	printf("a : %s\n", a); // a has a string.
    	printf("b : %s\n", b); // b is yet NULL.
    	printf("c : %s\n", c); // c is yet NULL.
    
    	/* memory to b is allocated in main(). */
    	b = (char*)malloc(strlen(a) + 1);
    
    	scpy1(b, a); // b is passed with its already allocated memory.
    	scpy2(c, a); // but c is passed as NULL.
    
    	printf("a : %s\n", a);
    	printf("b : %s\n", b); // shows a is copied to b.
    
    	printf("c : %s\n", c); // shows c is still NULL.
    
    	/* --------------------------------------------- */
    	/* Why scpy2() behaves for c the way it is?      */
    	/* How can I assign memory to c inside scpy2()?  */
    	/* --------------------------------------------- */
    }
    
    /* scpy1() copies string to a same size char array. */
    void scpy1(char d[], const char s[])
    {
    	int i = 0;
    	int j = 0;
    
    	if ((s != NULL) && (d != NULL))
    	{
    		i = strlen(s);
    
    		for (j = 0; j <= i; ++j)
    		{
    			d[j] = s[j];
    		}
    	}
    }
    
    /* scpy2() tries to allocate memory to d[] inside the body. */
    void scpy2(char d[], const char s[])
    {
    	int i = 0;
    	int j = 0;
    
    	if ((s != NULL) /*&& (d = NULL)*/)
    	{
    		i = strlen(s);
    
    		/* Try to allocate memory inside this scpy2(). */
    		d = (char*)malloc(strlen(s) + 1);
    	 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
    
    		for (j = 0; j <= i; ++j)
    		{
    			d[j] = s[j];
    		}
    	}
    }

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    memory for char d[] already exists, you need to realloc()
    check the unix man pages.

  3. #3
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    It beacuse it is passing the address of c by value so you can't modify its value. The easiest way is to do something like this.
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    /* scpy1() copies string to a same size char array. */
    /* If you re using pointers why are you putting an array for a paramter?*/
    void scpy1(char *d, const char *s);
    
    /* scpy2() tries to allocate memory to d[] inside the body. */
    char *scpy2(char *d, const char *s);
    
    int main()
    {
    	char a[] = "This is a line of ASCII string";
    	char* b = NULL;
    	char* c = NULL;
    
    	printf("a : %s\n", a); /* a has a string. */
    	printf("b : %s\n", b); /* b is yet NULL. */
    	printf("c : %s\n", c); /* c is yet NULL. */
    
    	/* memory to b is allocated in main(). */
    	/* you don't have to cast malloc */
    	b = malloc(strlen(a) + 1);
    
    	scpy1(b, a); /* b is passed with its already allocated memory. */
    	c = scpy2(c, a); /* but c is passed as NULL. */
    
    	printf("a : %s\n", a);
    	printf("b : %s\n", b); /* shows a is copied to b. */
    
    	printf("c : %s\n", c); /* shows c is still NULL. */
    
    	/* --------------------------------------------- */
    	/* Why scpy2() behaves for c the way it is?      */
    	/* How can I assign memory to c inside scpy2()?  */
    	/* --------------------------------------------- */
    	getchar();
    	free(b);
    	free(c);
    	return 0;
    }
    
    /* scpy1() copies string to a same size char array. */
    void scpy1(char *d, const char *s)
    {
    	int i = 0;
    	int j = 0;
    
    	if ((s != NULL) && (d != NULL))
    	{
    		i = strlen(s);
    
    		for (j = 0; j <= i; ++j)
    		{
    			d[j] = s[j];
    		}
    	}
    }
    
    /* scpy2() tries to allocate memory to d[] inside the body. */
    char *scpy2(char *d, const char *s)
    {
    	int i = 0;
    	int j = 0;
    	   
    	if ((s != NULL) /*&& (d = NULL)*/)
    	{
    		i = strlen(s);
    
    		/* Try to allocate memory inside this scpy2(). */
    		d = malloc(strlen(s) + 1);
    		
    	 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
    
    		for (j = 0; j <= i; ++j)
    		{
    			d[j] = s[j];
    		}
    	}
    	return d;
    }
    Woop?

  4. #4
    Registered User
    Join Date
    May 2006
    Posts
    4
    $ man realloc

    Says in fourth paragraph of DESCRIPTION:

    "realloc() changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged to the minimum of the old and new sizes; newly allocated memory will be uninitialized. If ptr is NULL, the call is equivalent to malloc(size); if size is equal to zero, the call is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to malloc(), calloc() or realloc()."
    I think in this case there is no difference in using malloc() or realloc(), since c is passed as a NULL (value equal to 0) pointer to scpy2().

  5. #5
    Registered User
    Join Date
    May 2006
    Posts
    4
    prog-bman wrote:

    Code:
    char *scpy2(char *d, const char *s)
    but I have a constraint to keep the return type of scpy2() as int. I have kept it as void, just not to involve it, otherwise I have to return the status message of scpy2() in my actual function of my project.

    Therefore, I will appreciate an alternative. I want to assign value and manipulate to "c" inside scpy2().

  6. #6
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    I think this is more of a design problem then. keep the burden of memory allocation on the calling function, and call strncpy().

  7. #7
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    I really don't know an alternative because what you need to do is pass in a pointer to a pointer in which you pass the address of the pointer which is NULL so I mean unless someone else knows a solution here I sure don't.
    Example of what I am talking about
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    void function(int x);
    void pfunction(int *x);
    
    int main()
    {
        int x = 10;
        int *pointer = malloc(sizeof(int) );
        
        *pointer = 15;
        
        /*Do these do anything???*/
        function(x);
        pfunction(pointer);
        
        printf("x = %d\n", x);
        printf("pointer = %d\n", *pointer);
        
        getchar();
        
        return 0;    
    }
    
    void function(int x)
    {
        /*We know this really doesn't change x's value in the calling function*/
        x = 10;
    }
    
    void pfunction(int *x)
    {
        /*Same thing applies here but with memory address!*/
        x = NULL;
    }
    Last edited by prog-bman; 05-25-2006 at 03:21 AM.
    Woop?

  8. #8
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    Something like this seems to work I have no idea if this is the proper way to do this.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    void pfunction(int **x);
    
    int main()
    {
        int i;
        int *pointer = NULL;    
        pfunction(&pointer);
           
        for(i = 0; i < 5; i++){
            printf("pointer = %d\n", pointer[i]);
        }    
        getchar();
        
        return 0;    
    }
    
    void pfunction(int **x)
    {
        int i;
        /*Allocate it for 5 variables*/
        *x = malloc(sizeof(int) * 5);
        for(i = 0; i < 5; i++){
            (*x)[i] = i + 10;
        }
    }
    quzah, prelude?
    Woop?

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Let's look at your post:

    You just post code, and give no description of your issue at all, other than a comment somewhere in all of your code. People that read these forums don't want to read your entire program just to hunt down a comment that may or may not be there. More often than not, it'll just get ignored. The only reason I looked at it, is because I read the thread from the bottom to the top.

    Your code is littered with incorrect issues. This is fine, in that you're posting to actually learn something. Or that's what we hope anyway.

    First one:
    Code:
    /* scpy2() tries to allocate memory to d[] inside the body. */
    void scpy2(char d[], const char s[]);
    Luck for you arrays degrade into pointers to the type of their first element. But luck aside, this doesn't even make sence. You don't allocate space for arrays. Arrays are created at compile time (C99 excluded), as a set size. Thus, you wouldn't be passing an array to this. Your argument you would be passing wouldn't even match up to this function prototype, assuming more luck and somehow it worked out. You'd end up doing something like:
    Code:
    char *foo;
    ...
    scpy2( foo, ... );
    foo isn't an array, so it wouldn't fit your prototype. Again, ignoring the fact that you purely luck out here with array to pointer degradation. The syntax logic of it doesn't fit. People should think more about what it is they're trying to do.

    Here's your next one...
    Code:
    void main()
    There's a FAQ on this. Go read it.

    Code:
    char* b = 0;
    char* c = 0;
    Zero does not a pointer make. This isn't C++ or Java, this is C. Thus, you should be assigning NULL to pointers. Not zero.

    Now why would you dod this?
    Code:
    printf("b : %s\n", b); // b is yet NULL.
    printf("c : %s\n", c); // c is yet NULL.
    Don't try and dereference null values. Bad programmer. You luck out again in the way that prinf handles NULL and null characters.

    No need to typecast malloc and its family members...
    Code:
    	/* memory to b is allocated in main(). */
    	b = (char*)malloc(strlen(a) + 1);
    There's a FAQ on that too.

    You've already been told what's wrong with this.
    Code:
    scpy2(c, a); // but c is passed as NULL.
    But even if you hadn't been, c is not an array. It doesn't match your prototype. Luck again on your part, because I seriously doubt you knew arrays degrade into pointers to their first element, considering the rest of your code. Even if it does, it's ugly syntax the way you attempt to use it.

    Code:
    printf("c : %s\n", c); // shows c is still NULL.
    
    	/* --------------------------------------------- */
    	/* Why scpy2() behaves for c the way it is?      */
    	/* How can I assign memory to c inside scpy2()?  */
    	/* --------------------------------------------- */
    Pointer to a pointer. Or return it and assign it that way. Those are your only options.


    Code:
    /* scpy1() copies string to a same size char array. */
    void scpy1(char d[], const char s[])
    {
    	int i = 0;
    	int j = 0;
    
    	if ((s != NULL) && (d != NULL))
    I hate your abuse of syntax here. You don't test an array to see if it is null. Arrays are never null. They just exist. Pointers however, can be NULL.

    The rest we've gone over already, so I'll stop there.


    Quzah.
    Hope is the first step on the road to disappointment.

  10. #10
    Registered User
    Join Date
    May 2006
    Posts
    4
    To prog-bman:

    Thank you very much for your kind help and guidance. I did what you told before but what I was missing was writing
    Code:
    *d[j] = s[j];
    instead of
    Code:
    (*d)[j] = s[j];
    in scpy2(), when I kept its signature as
    Code:
    void scpy2(char* d[], const char s[])
    .

    So I was getting seg faults due to this. Since your support corrected it, hence it let me catch my mistake. Again thanks for your kind views and help. But I understood your call to quzah only after reading his reply, what you wanted from him to say on the topic.

    Now To quzah:

    Thanks indeed for your both kind and harsh favor. Seems you like to defend C as much as you can.

    I posted the commented code, since a programming language is like a human language. It is used for expressing your thoughts, views and actions, just the same as what you do in a natural language. But it's depends upon the abilities of the person using it.

    quzah:
    Your code is littered with incorrect issues.
    That's why I am here.

    quzah:
    This is fine, in that you're posting to actually learn something.
    otherwise what was the need to post my stupidness on this forum.

    Then your guidelines about C arrays. I must say that since arrays are implemented as pointers in C, so you must think about them as handling pointers, which you called as array to pointer degradation. The array[] type syntax is not enough all the times. I know my ugliness when treating arrays.

    quzah:
    Don't try and dereference null values. Bad programmer.
    Yeah, I am a bad programmer. But I don't dereference NULL pointers. That's why I check a pointer as not NULL before dereferencing it, about which you said "I hate your abuse of syntax here."

    You luck out again in the way that prinf handles NULL and null characters.
    I must say that I knew the behavior of printf() what it does in case of NULL char*.

    About not casting a void* in assigning it to a defined type: it's a syntax error in C++ if you try to assign a void* without a cast. And this seems logical and apt, even if not used in C.

    But in a whole I thank you again for your time and guidance.

    Thanks all of you for your 71 views of this thread, by the time I am writing this.

  11. #11
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by see_c
    But I understood your call to quzah only after reading his reply, what you wanted from him to say on the topic.
    Actually, I believe they weren't quite sure the code they posted was the correct way to handle the pointer-to-pointer scenario. I interpreted it as a 'can you double check this work' type of comment. I post whatever's on my mind, regardless of what people do or do not want me to post.
    Quote Originally Posted by see_c
    Thanks indeed for your both kind and harsh favor. Seems you like to defend C as much as you can.
    I like the language, and find it better to be pedantic with it than lax. This is one of those 'by the letter of the law' type of things.
    Quote Originally Posted by see_c
    That's why I am here.
    Good to hear. Most people just show up to get their homework done for them.

    Quote Originally Posted by see_c
    Then your guidelines about C arrays. I must say that since arrays are implemented as pointers in C, so you must think about them as handling pointers, which you called as array to pointer degradation. The array[] type syntax is not enough all the times. I know my ugliness when treating arrays.
    They are not implemented as pointers. They are distinctly different. Prior to C99, arrays were always a fixed size. You created their size at compile time, and they were always that size. Consider:
    Code:
    int array[ 5 ];
    This array will always be 5 elements in size. It cannot and will not ever change. Also, 'array' will never be NULL, because it will always be "pointing at" an array of five elements. "pointing at" is a bad term for it, because "array" is not a pointer. Now pass it to a function:
    Code:
    void foo( int array[] )
    {
        ...
    }
    ...
    foo( array );
    This really gets translated to this:
    Code:
    void foo( int *array )
    {
        ...
    }
    foo( array );
    The array degrades into a pointer to the type of its first element. You will encounter problems if you don't grasp this when you try to use multi-dimension arrays with functions especially. At any rate, since it becomes a pointer to that type, you can do this:
    Code:
    void foo( int *array )
    {
        int x;
    
        array = &x;
        ...
    }
    Now for the scope of this function, 'array' is simply a pointer to an integer. Because C is a 'by value' language, and because the way array names are treated as pointers to the first element, you can really create legal confuzing code. The above is perfectly valid, but will not have the effect you might expect. The above change does nothing to the array outside of the function.

    However, my point about arrays never being NULL was because...
    Code:
    int array[ 5 ];
    
    if( array == NULL )
    {
        printf( "Legal to do, but..." );
    }
    else
    {
        printf( " ...pretty damn pointless." );
    }
    Pretty damn pointless. The array will never be NULL, because it will always "point to" its contents. When passed to a function, I find it more fitting to test a pointer for NULL than an array, because while technically allowable, an array can never be NULL, but a pointer can.
    Quote Originally Posted by see_c
    But I don't dereference NULL pointers. That's why I check a pointer as not NULL before dereferencing it, about which you said "I hate your abuse of syntax here."
    That's true. You didn't. I misrepresented that I suppose. You passed it to a function, which is fine.

    Quote Originally Posted by see_c
    I must say that I knew the behavior of printf() what it does in case of NULL char*.
    Aye.

    Quote Originally Posted by see_c
    About not casting a void* in assigning it to a defined type: it's a syntax error in C++ if you try to assign a void* without a cast. And this seems logical and apt, even if not used in C.
    There's a FAQ on why not to typecast it in C. Basically in C you never need to typecast the assignment of a void pointer to another type. There's no point to it, it has no purpose, and as such, is just wasted keystrokes. Additionally, it could mask your failure to include an appropriate header.

    Quzah.
    Hope is the first step on the road to disappointment.

  12. #12
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    I still think I gave the best advice: dump your crappy implementation and keep the burden of memory allocation on the calling function. You want to copy only a number of characters? Fine. allocate enough memory before hand, and call your function and tell it exactly how many characters to copy.

    Oh but the standard does this already with strncpy().

  13. #13
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    You also gave the crappiest advice, with your first post, so I guess you balance out. Oh and strncpy is not guarinteed to null terminate strings.


    Quzah.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Including lib in a lib
    By bibiteinfo in forum C++ Programming
    Replies: 0
    Last Post: 02-07-2006, 02:28 PM
  2. const at the end of a sub routine?
    By Kleid-0 in forum C++ Programming
    Replies: 14
    Last Post: 10-23-2005, 06:44 PM
  3. Compiler "Warnings"
    By Jeremy G in forum A Brief History of Cprogramming.com
    Replies: 24
    Last Post: 04-24-2005, 01:09 PM
  4. c++ linking problem for x11
    By kron in forum Linux Programming
    Replies: 1
    Last Post: 11-19-2004, 10:18 AM
  5. Quick question about SIGSEGV
    By Cikotic in forum C Programming
    Replies: 30
    Last Post: 07-01-2004, 07:48 PM