Thread: strings Vs. Char pointers

  1. #1
    Registered User
    Join Date
    Feb 2008
    Posts
    9

    Question strings Vs. Char pointers

    Hello,
    I wanna illustrate the difference between a char array (a string that is) and a pointer to char using a simple function which say capitalizes all the letters of a given string.

    To that affect I have written a simple code which (hopefully) should be doing just that. I have a function which does the checkin g and the capitalizing part. The function accepts a char pointer as an argument so I pass it a char pointer once and a char array the other time.

    So I hope that the former one should give me a seg fault as i am trying to access and write back to a memory element which does not belong to the function (is it a scope issue or what??...im bedazled as of now). And yeah it does flag a seg fault for the former case.

    However when I pass the array (using the name of the array which is also a char pointer) it still flags the seg fault error!!!..why is that..

    heres the code:

    Code:
    #include <stdio.h>
    #include <ctype.h>
    
    void set2caps(char *);//func prototype for capitalizing letters of string
    
    int main()
    
    {
        char *str = "string for pointer";
     //   char str1[] = "string for array";
    
        set2caps(str);
        set2caps(str1);
    
        puts("strings displayed in caps\n");
    
      //  printf("str in caps is &#37;s\n",str);
        printf("str1 in caps is %s\n",str);
    
        return 0;
    }
    
    void set2caps(char *str_hld)
    
    {
        unsigned int chr_cnt = 0;
        char temp;
    
        while(str_hld[chr_cnt]) {
            if (!isupper(str_hld[chr_cnt]))
                temp = toupper(str_hld[chr_cnt]);
            str_hld[chr_cnt] = temp;
            chr_cnt++;
        }
    }
    Last edited by aijazbaig1; 02-01-2008 at 01:36 PM. Reason: I asked a wrong question!!..geez

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
    char *str = "string for pointer";
    ...is actually:
    Code:
    const char *str = "string for pointer";
    Because the memory in which the string is stored is read-only.

    I also don't think you should try to prove that char* is not an array and char[] is, because technically, they are almost the same. I see both are strings. I see arrays as pointers due to their underlying nature.

    Code:
    set2caps(str1);
    Works just fine.

    Now, if you do like this:
    Code:
    const char str2[] = "string for pointer";
    char* str = malloc( sizeof(str2) );
    strcpy(str, str2);
    set2caps(str);
    It will work fine, you'll see.
    Last edited by Elysia; 02-01-2008 at 01:35 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Both strings are pointing to literal string constants. Modifying them will yield unexpected results. At best it will blow up; at worst it will appear to do what you wanted.

  4. #4
    Registered User
    Join Date
    Feb 2008
    Posts
    9
    well....
    they are not the same if you care about the specifics.

    A char pointer is a variable. It can be the lvalue of an expression while the name of an array is a constant. So it cannot be the lvalue of an expression as it is a constant pointer.

    I actually asked a wrong question as the program does work fine for the str1 character string..which I would change in the question now...

    However my main question is about the scope...what about the scope...

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by aijazbaig1 View Post
    well....
    they are not the same if you care about the specifics.

    A char pointer is a variable. It can be the lvalue of an expression while the name of an array is a constant. So it cannot be the lvalue of an expression as it is a constant pointer.
    Well, see, that's because the array is a special syntax for pointers. You must specify the size to allocate, so therefore you use a special syntax. The compiler knows that it's more than one elements and thus won't allow you to assign something to it if it isn't the same size.
    That's how I see it. There was a discussion about how arrays are pointers just a while ago.

    However my main question is about the scope...what about the scope...
    The scope has nothing to do with it. Str can be modified if you malloc the memory and copy the string inside. The reason it didn't work was due to the read-only memory.
    So long as the original buffer doesn't go out of scope (which can never happen in a synchronous call), the buffer will remain valid and can be changed and manipulated however much you want within the function, and any other functions that has a pointer to it.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    I wanna illustrate the difference between a char array (a string that is) and a pointer to char
    Perhaps this might help (the code is C99, the concept is the same in C89):
    Code:
    #include <stdio.h>
    
    static void print_object(const void *p, size_t s)
    {
      printf("Object %p:\n", p);
      for(size_t i = 0; i < s; i++) printf("%hhu\n", ((unsigned char*)p)[i]);
    }
    
    int main(void)
    {
      char string1[] = "this is a string";
      const char *string2 = "this is a string";
    
      print_object(&string1, sizeof string1);
      print_object(&string2, sizeof string2);
    
      return 0;
    }
    Maybe just printing out the result of sizeof on each object is enough to show the difference, too. I guess it depends on how convincing you're trying to be.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I don't understand what you're trying to accomplish through this whole arrays are different that pointers?
    Many treat arrays as pointers and rightly so, as they basically the same thing.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User
    Join Date
    Feb 2008
    Posts
    9
    The scope has nothing to do with it. Str can be modified if you malloc the memory and copy the string inside. The reason it didn't work was due to the read-only memory.
    So long as the original buffer doesn't go out of scope (which can never happen in a synchronous call), the buffer will remain valid and can be changed and manipulated however much you want within the function, and any other functions that has a pointer to it.
    By mallocing the memory and then copying the string do you mean I should first allocate space for the string and the pass the memory head as a pointer to the function right?

    What exactly do you mean by the buffer not going out of the scope of the function?...like when I pass str1 to this function I do not get a seg fault. However it looks like the contents of the memory have remained unchanged as the string is exactly like before without any capitalization.

    And when I try to pass str to the function I get a seg fault right away...

    Whew ..this can get a bit confusing some times...:|

  9. #9
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    Well... Arrays are different than pointers, and the difference can come into play. As my example alluded to, applying & to a pointer to char yields something different than when it's applied to an array of char. A more common--from what I've seen--misconception is that an array of array (i.e. a 2d array) is the same thing as a pointer to pointer. I imagine there have been posts here where a person is confused as to why:
    Code:
    int f(int **a);
    int a[5][5];
    f(a);
    doesn't work, for example.

    There's no question that pointers and arrays are intimately connected, and that for the most part an array can be treated as a pointer to its first element. However, there is a difference, and it behooves a programmer to know what the difference is so it won't bite him.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    OK, so let me demonstrate:

    Code:
    int main()
    {
    	char* mystr = "My string";
    	foo(mystr); /* Will segfault because mystr is read-only */
    	char* mystr2 = malloc(sizeof("My string") + 1);
    	strcpy(mystr2, "My string");
    	foo(mystr2); /* Will work because you allocated memory you can read/write to */
    	char mystr3[] = "My string";
    	foo(mystr3); /* Works because it's read/write memory allocated on the stack */
    	return 0;
    }
    
    void foo(char* pStr)
    {
    	pStr[0] = toupper(pStr[0]);
    }
    This shows the difference between all 3 methods.
    Scope demonstration:

    Code:
    int main()
    {
    	char* pStr = foo(); /* Doesn't work! */
    	char mystr[] = "my string";
    	foo2(mystr); /* foo2 can do whatever it wants to mystr because it will go out of scope once main ends */
    }
    
    char* foo()
    {
    	char mystr[] = "my string";
    	mystr[0] = toupper(mystr[0]); /* Works because mystr exists in this function */
    	return mystr; /* Won't work because mystr will go out of scope */
    }
    
    void foo2(char* pStr)
    {
    	pStr[0] = toupper(pStr[0]);
    }
    Quote Originally Posted by cas View Post
    Well... Arrays are different than pointers, and the difference can come into play. As my example alluded to, applying & to a pointer to char yields something different than when it's applied to an array of char. A more common--from what I've seen--misconception is that an array of array (i.e. a 2d array) is the same thing as a pointer to pointer. I imagine there have been posts here where a person is confused as to why:
    Code:
    int f(int **a);
    int a[5][5];
    f(a);
    doesn't work, for example.

    There's no question that pointers and arrays are intimately connected, and that for the most part an array can be treated as a pointer to its first element. However, there is a difference, and it behooves a programmer to know what the difference is so it won't bite him.
    I'm assuming that the standard wants the compiler to have some kind of knowledge about what type is passed. But it doesn't really matter because even if you use such syntax, it's still used as a pointer, hence it is a pointer and not an array. You can't get the size of the array, you can't see the contents of the array because it's a pointer.
    Last edited by Elysia; 02-01-2008 at 03:04 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    Quote Originally Posted by Elysia View Post
    I'm assuming that the standard wants the compiler to have some kind of knowledge about what type is passed. But it doesn't really matter because even if you use such syntax, it's still used as a pointer, hence it is a pointer and not an array. You can't get the size of the array, you can't see the contents of the array because it's a pointer.
    I'm sorry, but I'm not sure what you're saying.

    The snippet I posted is not valid C: it requires a diagnostic. It also, I believe, illustrates that pointers and arrays are not the same thing and that the difference is not just some abstract concept. Trying to pass a 2d array to a function that expects a pointer to pointer is indeed something that newbies try.

    While it is important to know how arrays and pointers are similar, I feel that knowing the difference is just as important.

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    OK, so we know you can't just pass a 2D array as array**. That won't work.
    However, even so, you are accessing the array just like a 2D-pointer. That, in my book, makes it an array.
    I don't know why the standard requires you to specify the inner/outmost dimension, whichever it is, when passing 2D-arrays. I just don't. But it doesn't change the fact that after the function that takes the arguments acquires that variable, it's just like a pointer. Again.

    So, arrays are just pointers with special syntax. Makes sense if you think about it.
    I don't think you should teach arrays and pointers as different things. I believe in that teaching that arrays are pointers with special syntax. Because if you know how to use pointers, then you also know how arrays works.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by Elysia View Post
    However, even so, you are accessing the array just like a 2D-pointer.
    That's not really true: If a is defined as int a[10][10], a does not get passed into a function as a pointer to pointer, but a pointer to an array. (Array decay does not happen recursively, in other words.)

    Quote Originally Posted by Elysia View Post
    I don't know why the standard requires you to specify the inner/outmost dimension, whichever it is, when passing 2D-arrays.
    I believe you, as breathtaking an admission as that is. Think for a minute: If you had a[10][10], so you needed to store 100 integers in memory somewhere, how would you arrange it so you could find a[0][1] and a[1][0] easily?

    Right: you'd store things in rows, so that all the a[0][m]'s appear first, then all the a[1][m]'s next, and so on. In fact, you would know that the offset for a[x][y] would be 10*x+y (times the size of an int, of course). Now, if all you had was a bare pointer to the first element, how would you find a[1][0]?

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Makes sense. I haven't used many 2D arrays. Believe it or not. The only times I have, it's been local. Thanks to CString and std::vector for that!
    But it doesn't change that the array is basically a pointer. The compiler just needs to know how to calculate the offset. You could see an array as a tool for helping a programmer use a contiguous memory block with pointers.
    It will still just use a pointer and calculate the offset.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by tabstop View Post
    Now, if all you had was a bare pointer to the first element, how would you find a[1][0]?
    The same way that you would know how to find a[5] in a 1D array. You'd need to pass the size of the array to the function as well as the array. So if you pass a 2D array, I'm not sure why a pointer-to-pointer doesn't work since you could just pass 2 sizes along with the pointer?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. copying pointers
    By Tom Bombadil in forum C Programming
    Replies: 10
    Last Post: 05-22-2009, 01:26 PM
  2. Replies: 16
    Last Post: 10-29-2006, 05:04 AM
  3. Help with calloc and pointers to strings.
    By sweetarg in forum C Programming
    Replies: 1
    Last Post: 10-24-2005, 02:28 PM
  4. code condensing
    By bcianfrocca in forum C++ Programming
    Replies: 4
    Last Post: 09-07-2005, 09:22 AM
  5. String sorthing, file opening and saving.
    By j0hnb in forum C Programming
    Replies: 9
    Last Post: 01-23-2003, 01:18 AM