Thread: Learning Pointers

  1. #1
    Registered User
    Join Date
    Sep 2005
    Posts
    34

    Learning Pointers

    Long story short I'm on spring break and I've decided to spend my time figuring pointers out. Since I'll probably have a lot of questions on the subject I decided to make one thread and post all my questions here.

    First of all I'm trying to go through the pointer exercises in K&R. After a few failures I found that the function
    Code:
    void strcpy(char *s, char *t){
        while((*s++ = *t++) != '\0'){
            s++;
            t++;
        }
    }
    causes my computer to crash. Why does my computer crash when I call the function? Here is my entire code:

    Code:
    #include <stdio.h>
    
    void strcpy(char *s, char *t);
    
    
    int main(){
        char *a = "first";
        char *b = "second";
        stcpy(a,b);
        printf("%s",a);
        getchar();
    }
    
    void strcpy(char *s, char *t){
        while((*s++ = *t++) != '\0'){
            s++;
            t++;
        }
    }

  2. #2
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Code:
        char *a = "first";
        char *b = "second";
    When you set a pointer to a string constant like this, it's pointing to read-only memory. You're also trying to copy 1 more character than you'd have room for (if the method worked). You're better off using arrays like so:
    Code:
      char a[7] = "first";
      char b[7] = "second";
    I'm not sure why the program crashed your computer. It should just kill the program unless you're using something ancient that doesn't have a virtual memory manager.
    If you understand what you're doing, you're not learning anything.

  3. #3
    Registered User
    Join Date
    Sep 2005
    Posts
    34
    Quote Originally Posted by itsme86 View Post
    Code:
        char *a = "first";
        char *b = "second";
    When you set a pointer to a string constant like this, it's pointing to read-only memory. You're also trying to copy 1 more character than you'd have room for (if the method worked). You're better off using arrays like so:
    Code:
      char a[7] = "first";
      char b[7] = "second";
    I'm not sure why the program crashed your computer. It should just kill the program unless you're using something ancient that doesn't have a virtual memory manager.
    The exercise says to use a pointer string. And sorry I didn't mean crash computer I meant crash the program.

  4. #4
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Your strcpy() function is still using pointers to the strings. I think gcc has a --writable-strings option if you're really dying to learn the wrong way of doing it
    If you understand what you're doing, you're not learning anything.

  5. #5
    Registered User
    Join Date
    Sep 2005
    Posts
    34
    Quote Originally Posted by itsme86 View Post
    Your strcpy() function is still using pointers to the strings. I think gcc has a --writable-strings option if you're really dying to learn the wrong way of doing it
    Yes tried your advice and the program still crashes.

  6. #6
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    What exactly does your program listing look like now? It runs fine on mine. One thing to note is that you're calling stcpy() in main(), but you're actually defining strcpy() and have a function prototype by that name as well. strcpy() is a standard string function in C, so I would recommend changing the prototype and function declaration to stcpy().

    Also, the function has a bug in it which causes it to only copy every other character. And if the string has an odd number of characters in it (not including the nul-terminating 0) it could get funky. This is what runs fine for me:
    Code:
    #include <stdio.h>
    
    void stcpy(char *s, char *t);
    
    
    int main(){
        char a[7] = "first";
        char b[7] = "second";
        stcpy(a,b);
        printf("&#37;s\n",a);
        getchar();
    }
    
    void stcpy(char *s, char *t){
        while((*s++ = *t++) != '\0'){
            s++;
            t++;
        }
    }
    If you understand what you're doing, you're not learning anything.

  7. #7
    Registered User
    Join Date
    Sep 2005
    Posts
    34
    Odd, it looks just like that and it still crashes. My computer does act weird but I wouldn't think that it would cause a program like this to crash...

    edit: Ok had to do something with projects and code blocks. Fixed if I just make one file.
    Last edited by mrcheesypants; 04-03-2007 at 03:30 PM.

  8. #8
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Well, maybe fixing the bugs in stcpy() will stop it from crashing. You should only increment s and t once each time through the loop instead of twice.
    If you understand what you're doing, you're not learning anything.

  9. #9
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    BTW,
    Code:
    printf("&#37;s\n",a);
    is the same as
    Code:
    puts(a);
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  10. #10
    Registered User
    Join Date
    Sep 2005
    Posts
    34
    Ok for exercise 5-3 in K&R (which is write a strcat function using pointers) I got
    Code:
    #include <stdio.h>
    
    void stcat(char *s, char *t);
    int stlength(char *s);
    
    int main(){
        char a[] = "first";
        char b[] = "second";
        stcat(a,b);
        printf("&#37;s\n",a);
        getchar();
    }
    
    void stcat(char *s, char *t){
        int a = stlength(s);
        int b = stlength(t);
        int c = a +b;
        for(int i = 0; i < c; i++ , s++){
                    if(i >=a){
                        *s = *t;
                        *t++;
                    }
        }
    }
    
    int stlength(char *s){
        int i = 0;
        while (*s++ != '\0')
            i++;
        return i;
    }
    I got the desired result but I have the feeling that there is a concept I missed and that there is a more efficient way of doing the exercise. Is there such a concept I missed or am I just a little paranoid?

    edit: oh and thanks dwks I'll keep that in mind.

  11. #11
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    you probably didnt get the desired result, and if you did, then try it on another computer, or reboot and try again and you probably wont. take a close look at the output again.

    in the main you have a char* 'a' of length 6 (5 + '\0' automatically appended), which you pass to strcat, with b.

    in the for loop of strcat you are setting the indices of s ('a' in main) that arent 'yours'. you have declared a variable of length 6, and thats fine and you can do whatever you want with it.

    however, on the first true condition of your if statement in the while loop, you will be writting into index 6 (ie 7th character)... but i thought you only 'wanted' 6? the data in the 7th (and other subsequent indices/data) dont 'belong' to you. that data might belong to another program and writing to it will adversely affect that program (and probably lead to a crash).

    you have to remember C is a very advanced and powerful language, and the operating system will let you do almost anything you write in your code, even if you shouldnt be able to. Java, for example, wouldnt let you do this.

    in your strcat function, (i dont think) theres a way of making _sure_ your not overwriting something you shouldnt be, you just assume that person calling the function is passing s,t, where s is big enough for t also. again, this is C, so this library function assumes this--that the programmer knows what hes doing.

    the following is an example of using this code safetly:
    Code:
    #include <stdio.h>
    
    void stcat(char *s, char *t);
    int stlength(char *s);
    
    int main(){
        char a[50]="first";
        char b[] = "second";
        stcat(a,b);
        printf("&#37;s\n",a);
        getchar();
    }
    
    void stcat(char *s, char *t){
        int a = stlength(s);
        int b = stlength(t);
        int c = a +b;
        int i;
        for(i = 0; i < c; i++ , s++){
                    if(i >=a){
                        *s = *t;
                        *t++;
                    }
        }
    }
    
    int stlength(char *s){
        int i = 0;
        while (*s++ != '\0')
            i++;
        return i;
    }
    'a' declared in main is large enough to safely hold the data in 'b' without going out of bounds of whats yours.

    a safer way to make sure you dont overwrite something that isnt yours is to dynamically allocate an array, of size 'c' (c + 1 maybe?). you would then change return type of strcat to char* and return your new array.

    edit: the following is an example of this
    Code:
    #include <stdio.h>
    
    char* stcat(char *s, char *t);
    int stlength(char *s);
    
    int main(){
        char a[]="first";
        char b[] = "second";
        
        char* x = stcat(a,b);    
        printf("%s\n",x);
        
        free(x);
        // note that 'strcat' creates a variable dynamically. if you dont use free(), then that space
        // will be allocated until you reboot.. this is a memory leak
        // always use free() to prevent this, just before your done with the variable
        getchar();
    }
    
    char* stcat(char *s, char *t){
        int a = stlength(s);
        int b = stlength(t);
        int c = a +b;
        int i;
        
        char* newstr = malloc(c * sizeof(char)); // sizeof(char) == 1 so you can use either
        // if you dont know dynamic memory then
        // you can stick with what you had before, but use it safetly    
    
        // its always wise to check if malloc returned null, ie: if (newstr == null)
        // this could happen if computer is out of free memory, in which case you should
        // not continue the following commands
    
        for (i = 0; i < a; i++)
            newstr[i] = s[i];
        
        // note that 'i' still keeps its value here, since its scope is this entire function.
        // on this line, i = a
        
        for (; i < c; i++) // dont need the first 'initialization' portion, since i still = a
            newstr[i] = t[i-a]; // if the i-a is confusing try and trace it on paper
            
        newstr[c] = '\0'; // always apppend null character 
        
        return newstr;
    }
    
    int stlength(char *s){
        int i = 0;
        while (*s++ != '\0')
            i++;
        return i;
    }
    Last edited by nadroj; 04-04-2007 at 06:27 PM. Reason: added example

  12. #12
    Registered User
    Join Date
    Sep 2005
    Posts
    34
    Ah thanks for the info! I don't understand dynamic memory yet but wouldn't my same function cause a memory link no matter what size string s is because it looks for the '/0'? Or is the '/0' added right after the last piece of data is inserted?

  13. #13
    Registered User
    Join Date
    Oct 2006
    Location
    Canada
    Posts
    1,243
    you can use your initial function (from post #10), however you have to call it as i did in the first code portion of my last post. that is, call it with a variable that is large enough to store both char*s.

    wouldn't my same function cause a memory link (sp: leak) no matter what size string s is because it looks for the '/0'? Or is the '/0' added right after the last piece of data is inserted?
    i dont exactly understand what your asking.
    in main, with "char a[50]="first";" the contents of a will be:
    a[0] = 'f'
    a[1] = 'i'
    a[2] = 'r'
    a[3] = 's'
    a[4] = 't'
    a[5] = '\0'
    a[6...49] = (maybe undefined, maybe empty, i dont know)
    the null character (in a[5]) is automatically added. the variable 'a' still 'owns' a[0-49] and can do whatever you want with it, safetly.

    the operating system or compiler wont stop you from doing anything with a[>49], so the function has no way of knowing if its doing something it shouldnt be.. its only doing what it was asked to, and assumes the caller passed the first argument large enough to store both.

    in the second example where i used free(x), it will free the entire array and there will be no memory leak.. if thats what you were asking.
    Last edited by nadroj; 04-04-2007 at 07:34 PM.

  14. #14
    Registered User
    Join Date
    Sep 2005
    Posts
    34
    Yeah you answered what I was asking. My communication skills are lacking. Thanks again for your help it has been very insightful.

  15. #15
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > char* newstr = malloc(c * sizeof(char));
    You forgot to add 1 to store the \0

    > if the i-a is confusing try and trace it on paper
    Or create another variable, so one indexes the source string (which is reset) and one for the destination string (which isn't reset).

    > a[6...49] = (maybe undefined, maybe empty, i dont know)
    As written, the whole of the remainder of the array is filled with \0.

    > will be allocated until you reboot.. this is a memory leak
    Most good operating systems reclaim the space when the program exits.
    But the point is valid none the less.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. array of pointers to an array pointers
    By onebrother in forum C Programming
    Replies: 2
    Last Post: 07-28-2008, 11:45 AM
  2. Hey guys..need help on pointers
    By Darkozuma in forum C++ Programming
    Replies: 5
    Last Post: 07-25-2008, 02:57 PM
  3. delete and delete[]
    By Hunter2 in forum C++ Programming
    Replies: 13
    Last Post: 06-26-2003, 04:40 AM
  4. Pointers on pointers to pointers please...
    By Morgan in forum C Programming
    Replies: 2
    Last Post: 05-16-2003, 11:24 AM
  5. Staticly Bound Member Function Pointers
    By Polymorphic OOP in forum C++ Programming
    Replies: 29
    Last Post: 11-28-2002, 01:18 PM