Thread: Why exactly does this work?

  1. #1
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827

    Why exactly does this work?

    Why exactly does this work to get the position of a char inside a string?

    Code:
    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    int main() {
    
      char axle[] = "axle";
      char* start_ptr = strchr(axle, 'a');
      size_t start_pos = start_ptr - axle;
      cout<< "start_pos = " << start_pos <<endl;
      start_ptr = strchr(axle, 'x');
      start_pos = start_ptr - axle;
      cout<< "start_pos = " << start_pos <<endl;
      start_ptr = strchr(axle, 'l');
      start_pos = start_ptr - axle;
      cout<< "start_pos = " << start_pos <<endl;
      start_ptr = strchr(axle, 'e');
      start_pos = start_ptr - axle;
      cout<< "start_pos = " << start_pos <<endl;
      
      return 0;
    
    }
    http://codepad.org/HOX9DT3z

    My confusion arises from "start_ptr - axle", since start_ptr is a char pointer storing an address of a char element of a char array, and I can't see why subtracting the array "axle" from that would result in getting the correct position/index number (though counting from 0, since its an array) of a char inside a char array. I know identifiers for arrays are really just referring to pointers to the first element of the array, but even if you think of one memory address subtracting another from it, it still wouldn't be single digit numbers like 0, 1, 2, and 3.
    Last edited by Programmer_P; 01-04-2011 at 09:59 PM.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    By definition, arrays are stored with all the elements next to each other. So if the first has address 8000, the next character must needs have address 8001, and the next must have 8002, etc.

  3. #3
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Also, pointers know something about the sizes they point to:
    Code:
    #include <iostream>
    
    int main() {
    
        char bob[3];
        int foo[3];
        ptrdiff_t distance;
        distance = &bob[1] - bob;
        std::cout << "The distance of one character is " << distance << std::endl;
        distance = &foo[1] - foo;
        std::cout << "The distance of one integer is " << distance << std::endl;
        return 0;
    }

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Programmer_P View Post
    My confusion arises from "start_ptr - axle", since start_ptr is a char pointer storing an address of a char element of a char array, and I can't see why subtracting the array "axle" from that would result in getting the correct position/index number (though counting from 0, since its an array) of a char inside a char array.
    Say the first element is stored at 0x800.
    Say that the Nth element is stored at 0x808.
    So start_ptr would get the value 0x808. Now, if you do start_ptr - axle, where axle is an array, then axle decays into a pointer to its first element, that is, 0x800. So you do 0x808 - 0x800, which is 0x8 or 8.

    I know identifiers for arrays are really just referring to pointers to the first element of the array...
    Incorrect. An array is not a pointer to its first element. When you use the array's name in certain contexts, it decays to a pointer to its first element.
    Subtle, but important difference. Why is it there in the first place, you ask? Blame the C standard for that.

    ...but even if you think of one memory address subtracting another from it, it still wouldn't be single digit numbers like 0, 1, 2, and 3.
    This does not make sense.
    Subtract two memory addresses like integers and you would indeed get a single digit number.
    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.

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Incorrect. An array is not a pointer to its first element. When you use the array's name in certain contexts, it decays to a pointer to its first element.
    Subtle, but important difference.
    Not so subtle... In C, like in C++, an array type is the size of all it's elements, while a pointer type is the size of an address. When you declare an array, you are asking for a specific set of type variables to be allocated in automatic storage. That is reason enough to have separate types. In order to avoid much of the confusion both languages would have to copy arrays when they are passed to functions by default instead of pointing to a particular memory location. I personally couldn't find arrays very confusing. An array type variable will stay an array type for its whole life, but most actual uses for arrays involve expressions of pointer type. Consider the work involved in the expression array[i]: You aren't using the whole array right that moment, so sticking with an array type would just mean working with more information than you require. I would perhaps feel differently on this issue if there were bounds checking on said expressions, but people who want to change C or C++ in such a manner are a minority, so for me, paired with my understanding of the topic, there is no reason to keep various things as an array type if that's what needs to be.

    Why is it there in the first place, you ask? Blame the C standard for that.
    I don't really place blame anywhere, because in order to be honest about it, I would want to suggest an alternative for both languages, and I can't. I'm not smart enough.
    Last edited by whiteflags; 01-05-2011 at 12:15 PM.

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by whiteflags View Post
    Not so subtle... In C, like in C++, an array type is the size of all it's elements, while a pointer type is the size of an address. When you declare an array, you are asking for a specific set of type variables to be allocated in automatic storage. That is reason enough to have separate types. In order to avoid much of the confusion both languages would have to copy arrays when they are passed to functions by default instead of pointing to a particular memory location. I personally couldn't find arrays very confusing. An array type variable will stay an array type for its whole life, but most actual uses for arrays involve expressions of pointer type. Consider the work involved in the expression array[i]: You aren't using the whole array right that moment, so sticking with an array type would just mean working with more information than you require. I would perhaps feel differently on this issue if there were bounds checking on said expressions, but people who want to change C or C++ in such a manner are a minority, so for me, paired with my understanding of the topic, there is no reason to keep various things as an array type if that's what needs to be.
    Though I find no point in doing so. Why work with less information than what is available?
    Assigning arrays to arrays is forbidden; there is no reason copying arrays when passing to a function could be forbidden, as well.
    We do have the ability to take the address of an array, which would probably make sense to make a pointer to its first element, or do it ourselves, but instead we get another confusion pointer type.
    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.

  7. #7
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Though I find no point in doing so. Why work with less information than what is available?
    The language isn't using it anyway.

    Assigning arrays to arrays is forbidden; there is no reason copying arrays when passing to a function could be forbidden, as well.
    AFAIK, assigning an array to a function parameter is already forbidden because it can't happen by design. In any case, I would want copying arrays to work if my idea was a good one, and I don't think it is. I like things the way they are.

    We do have the ability to take the address of an array, which would probably make sense to make a pointer to its first element, or do it ourselves, but instead we get another confusion pointer type.
    But I don't see how replacing one confusing array to pointer type conversion with another kind of array to pointer type conversion solves any confusion problems. I don't get this, sorry.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. strcmp returning 1...
    By Axel in forum C Programming
    Replies: 12
    Last Post: 09-08-2006, 07:48 PM
  2. getline() don't want to work anymore...
    By mikahell in forum C++ Programming
    Replies: 7
    Last Post: 07-31-2006, 10:50 AM
  3. Why don't the tutorials on this site work on my computer?
    By jsrig88 in forum C++ Programming
    Replies: 3
    Last Post: 05-15-2006, 10:39 PM
  4. fopen();
    By GanglyLamb in forum C Programming
    Replies: 8
    Last Post: 11-03-2002, 12:39 PM
  5. DLL __cdecl doesnt seem to work?
    By Xei in forum C++ Programming
    Replies: 6
    Last Post: 08-21-2002, 04:36 PM