Char pointers in C

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • krreks
    New Member
    • Oct 2008
    • 22

    Char pointers in C

    Hi.

    I'm trying to figure out pointers and memory allocation in C. I've read quite a few explanations on the internet and have read in a few books that I've got, but I'm not so much smarter yet...

    What I want do do is to create an array of five pointers to characters... I want to make it possible to assign a pointer to the params array tohrough the setParams function. I don't understand what I have not gotten, but there is certainly something. It seems like this works:

    Code:
    char * val1 = malloc(30);
    free(val1);
    but this doesn't:

    Code:
    char * val1 = malloc(30);
    val1 = "Hei og hå!";
    free(val1);
    This seems logical to me, because the val1 variable is first instantiated with memory allocated and then set to "Hei og hå". I would assume the memory location returned from the malloc call would be lost, right?. The only walkaround for this problem as far as I have understood is to assign one char at the time and increase the pointer one position at the time and do

    Code:
    *val1 = 'H';
    and then increase the pointer with val1++ for each letter. It sounds too complicated to be right.. Or is it like this? Another problem with that solution is that when I've moved the pointer a few positions I have lost the start position of the var and is no longer able to free the var because I don't have the right position.

    If someone could straighten this out it would be awesome. I guess it's not so hard, but it is hard to get a grip on when you don't fully understand how the pointers work in C.

    The code I'm trying to get to work is to large to post here I think, but if I get the idea on how to get the following piece of code right, much is done I think.

    NOTICE! If your going to compile it, compile with "-DDEBUG -DSOLO" to get the main method and the includes in the compile.
    Code:
    #ifdef DEBUG
    #include <stdlib.h>
    #include <stdio.h>
    #endif
    
    #include "bitwise.h"
    
    int power(int num, int power) {
    	int i, res=1;
    	for(i=0; i<power; i++) {
    		res = res*num;
    	}
    	if(power==0)
    		return 1;
    	else
    		return res;
    }
    
    void setBit(unsigned char * map, int num, int val) {
    	if(val != getBit(map, num))
    		map[num/8] = (map[num/8]^power(2,7-(num%8)));
    }
    
    int getBit(unsigned char * map, int num) {
    	return ((map[num/8]>>(7-num)) & 1);
    }
    
    #ifdef SOLO
    char * setParam(char * params[], unsigned char * map, int n, char * val) {
    	params[n] = val;
    	setBit(map, n, 1);
    	return params[n];
    }
    
    char * getParam(char * params[], unsigned char * map, int n) {
    	//if(getBit(map, n))
    		return params[n];
    	//else
    	//	return NULL;
    }
    
    void removeParam(char * params[], unsigned char * map, int n) {
    	if(getBit(map, n)) {
    		printf("sletter: %x\n",params[n]);
    		free(params[n]);
    		setBit(map,n,0);
    	}
    }
    
    int paramUsed(char * params[], unsigned char * map, int n) {
    	return getBit(map, n);
    }
    
    int main() {
    	unsigned char status = 0;
    	char * params[5];
    	
    	char * val1 = malloc(30);
    	val1 = "Hei og hå!";
    	
    	printf("%s == %s\n",val1,setParam(&params[0], &status, 0, val1));
    	printf("%s\n",getParam(params, &status, 0));
    	printf("Used: %d\n",paramUsed(params, &status, 0));
    	removeParam(params, &status, 0);
    	printf("%s\n",getParam(params, &status, 0));
    	printf("Used: %d\n",paramUsed(params, &status, 0));
    	return 0;
    }
    #endif
    Thanks in advance :)

    K
  • boxfish
    Recognized Expert Contributor
    • Mar 2008
    • 469

    #2
    Code:
    char * val1 = malloc(30);
    val1 = "Hei og hå!";
    free(val1);
    Well hmm. I've only programmed in C++, so I'm not that familliar with malloc, but it seems you have to cast it to the data type you want; in this case, char*. As for copying a string into the allocated memory, you don't have to do it yourself; use the strcpy function. So the above code should be
    Code:
    char * val1 = (char *)malloc(30);
    strcpy(val1, "Hei og hå!");
    free(val1);
    Hope this helps.

    Comment

    • Tassos Souris
      New Member
      • Aug 2008
      • 152

      #3
      Code:
      char *val = malloc(30);
      
      /* Advice: change that to: */
      
      char *val = ( char * )calloc( 30, sizeof( char ) );
      This allocates a space for 30 characters. It returns the initial address and stores it in the val pointer variable. So, val now points to that space.

      Code:
      val = "....";
      Do not forget that strings in C are represented as sequences of characters in memory.
      In this statement, val gets the initial address of the string, so now it points there...

      When you do:
      Code:
      free( val );
      you have two problems:
      -> First, you have lost where the space you allocated with malloc (or calloc) resides in memory and you cannot free it anymore.
      -> Second, your program is most likely to get messy there.. free accepts a pointer earlier returned by a call to malloc, calloc or realloc.. In this case, the address of the string "..." is passed which might be in read-only memory (if your are lucky cause then you will get a assertion).

      The correst way to do this is to copy the string to the newly allocated space...

      hope i helped

      Comment

      • oler1s
        Recognized Expert Contributor
        • Aug 2007
        • 671

        #4
        Originally posted by boxfish
        I'm not that familliar with malloc, but it seems you have to cast it to the data type you want
        No. You don't have to cast malloc, and you probably don't want to, as it doesn't help but can hurt. Unless you want to compile under C++, C will implicitly do the cast.

        krreks, you wouldn't write val1++. You can index it, such as val1[2]. You essentially have an array (dynamically allocated), and you can index that array, right? Think about arrays.

        Also read http://c-faq.com/ on the relevant sections. The pointers vs. arrays section is particularly helpful.

        Comment

        • krreks
          New Member
          • Oct 2008
          • 22

          #5
          Thanks a lot for great pointers to answers! I had been scratching my head for quite a few hours and it was great getting some answers that was not in-a-conversation-answers in a mailing list :) A few new questions arises and it would be wonderfull to get some answers to those as well..

          1. So the strcpy seems to be the way to go then. I wonder though why this works like it does:

          Code:
          char * val1 = (char *) malloc(5);
          printf("%s\n",val1);
          strcpy(val1, "test");
          free(val1);
          printf("%s\n",val1);
          It seems to hold the value of the pointer even after it has been freed? Is that right or is there still an error?

          2. Is the following piece of code right? I have an array of pointers and want to point one of the elements in the array to a given memory location allocated for another pointer.

          Code:
          char * setParam(char * params[], unsigned char * map, int n, char * val) {
          	params[n] = val;
          	setBit(map, n, 1);
          	return params[n];
          }
          
          void removeParam(char * params[], unsigned char * map, int n) {
          	if(getBit(map, n)) {
          		printf("sletter: %s\n",params[n]);
          		free(params[n]);
          		setBit(map,n,0);
          	}
          }
          
          int main() {
          	unsigned char status = 0;
          	char * params[5];
          	
          	char * val1 = malloc(30);
          	strcpy(val1, "Hei og hå!");
          	setParam(&params[0], &status, 0, val1)
          	removeParam(params, &status, 0);
          }
          NOTICE! The get- and setBitmap functions is a bitmap to keep track of used and unused pointers and is known to work.

          It compiles and executes right, but here as well as the previos code, the value of the pointer is accesable after the memory is freed...

          Comment

          • drhowarddrfine
            Recognized Expert Expert
            • Sep 2006
            • 7434

            #6
            Freeing memory does not "reset" a pointer. It will still point at the address reserved by malloc. It's just that the memory itself is unused or, possibly, now used for something else.

            Comment

            • Banfa
              Recognized Expert Expert
              • Feb 2006
              • 9067

              #7
              It seems to me that you need to look up the standard library function strcpy.

              Comment

              • boxfish
                Recognized Expert Contributor
                • Mar 2008
                • 469

                #8
                Originally posted by oler1s
                You don't have to cast malloc, and you probably don't want to, as it doesn't help but can hurt.
                I thought you had to cast it because this code
                Code:
                char * val1 = malloc(30);
                strcpy(val1, "Hei og hå!");
                cout << val1;
                free(val1);
                didn't compile on my Dev-C++ compiler. It says
                invalid conversion from `void*' to `char*'
                The error went away when I did a typecast. Is there anything I'm doing wrong? I also found a couple of examples, like this one, which use a type cast.

                Comment

                • JosAH
                  Recognized Expert MVP
                  • Mar 2007
                  • 11453

                  #9
                  Originally posted by boxfish
                  I thought you had to cast it because this code
                  didn't compile on my Dev-C++ compiler. It says
                  invalid conversion from `void*' to `char*'
                  The error went away when I did a typecast. Is there anything I'm doing wrong? I also found a couple of examples, like this one, which use a type cast.
                  The OP is using C, you were using C++. In C you can freely implicitly cast to and
                  from a void* to any other type of pointer. In C++ the cast needs to be explicit.

                  kind regards,

                  Jos

                  Comment

                  • boxfish
                    Recognized Expert Contributor
                    • Mar 2008
                    • 469

                    #10
                    Okay, thanks, I get it. I had expected that all C code would compile for me, because of the backwards-compatibility thing.

                    Comment

                    • krreks
                      New Member
                      • Oct 2008
                      • 22

                      #11
                      Originally posted by drhowarddrfine
                      Freeing memory does not "reset" a pointer. It will still point at the address reserved by malloc. It's just that the memory itself is unused or, possibly, now used for something else.
                      That sounds right. I've really tried and failed a lot the last few days, but it's starting to pay off :)

                      Thanks a lot for all the answers, explanations and your time.

                      Yours sincerely

                      Comment

                      • Laharl
                        Recognized Expert Contributor
                        • Sep 2007
                        • 849

                        #12
                        Originally posted by boxfish
                        Okay, thanks, I get it. I had expected that all C code would compile for me, because of the backwards-compatibility thing.
                        Not all C is valid C++, just most of it.

                        Comment

                        Working...