strings Vs. Char pointers

This is a discussion on strings Vs. Char pointers within the C Programming forums, part of the General Programming Boards category; An array is not a pointer. The reason arrays appear to be pointers is that in most expressions, C will ...

  1. #31
    cas
    cas is offline
    Registered User
    Join Date
    Sep 2007
    Posts
    993
    An array is not a pointer. The reason arrays appear to be pointers is that in most expressions, C will convert an array into a pointer to its first element. This is apparently where the confusion comes in, and that's not surprising.

    Now, if you want to make a statement along the lines of "Ignoring a couple of corner cases, an array is a pointer," then you at least have a leg to stand on; if a C program can't tell the difference (and it can, of course, but let's pretend that the & and sizeof operators don't exist and that arrays of arrays don't exist), then there'd be no real reason to draw a distinction.

    And, generally speaking, you can get away with thinking that an array is a pointer; avoiding & and sizeof with arrays and avoiding multidimensional arrays is not a hard thing to do, I suppose, and in that case, as far as you care, arrays are pointers.

    Perhaps I've missed a corner case or two, but that's OK: I'm not trying to convince anybody that arrays should be treated as pointers, merely explaining why or how they can. I think C programmers should know the difference, but if you can get away with thinking they're the same, well, who am I to stop you?

  2. #32
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    22,918
    sizeof of a pointer will always return 4 on x86, and 8 on x64-64 I believe.
    Point is, an array is a pointer, but an array requires special syntax to define how many elements you are allocating. And it's even trickier with 2D-arrays since the compiler must know the number of columns in the dimension or it can't calculate a proper offset. In the end, it's all a pointer and an offset. The compiler just needs a little help when you define a 2D-array since it couldn't calculate the proper offset otherwise.

    The only exception to arrays not being a pointer is that you can do sizeof the array and it will return the array size, but only in the local function where it's defined. Because in that function, the compiler can clearly see that it defined as a pointer to storage of n elements. But when passing the array or pointer to a function, that information is now lost to the compiler.
    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. #33
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,166
    Point is, an array is a pointer, but an array requires special syntax to define how many elements you are allocating.
    To put things in a Standard perspective with C99:
    Quote Originally Posted by ISO/IEC 9899:1999 Section 6.2.5
    Any number of derived types can be constructed from the object, function, and incomplete types, as follows:
    • An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. Array types are characterized by their element type and by the number of elements in the array. An array type is said to be derived from its element type, and if its element type is T, the array type is sometimes called "array of T". The construction of an array type from an element type is called "array type derivation".
    • ...
    • A pointer type may be derived from a function type, an object type, or an incomplete type, called the referenced type. A pointer type describes an object whose value provides a reference to an entity of the referenced type. A pointer type derived from the referenced type T is sometimes called "pointer to T". The construction of a pointer type from a referenced type is called "pointer type derivation".


    These methods of constructing derived types can be applied recursively.

    Arithmetic types and pointer types are collectively called scalar types. Array and structure types are collectively called aggregate types.
    Quote Originally Posted by ISO/IEC 9899:1999 Section 6.3.2.1
    Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #34
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Elysia View Post
    sizeof of a pointer will always return 4 on x86, and 8 on x64-64 I believe.
    Point is, an array is a pointer, but an array requires special syntax to define how many elements you are allocating. And it's even trickier with 2D-arrays since the compiler must know the number of columns in the dimension or it can't calculate a proper offset. In the end, it's all a pointer and an offset. The compiler just needs a little help when you define a 2D-array since it couldn't calculate the proper offset otherwise.

    The only exception to arrays not being a pointer is that you can do sizeof the array and it will return the array size, but only in the local function where it's defined. Because in that function, the compiler can clearly see that it defined as a pointer to storage of n elements. But when passing the array or pointer to a function, that information is now lost to the compiler.
    Regarding 2D arrays, I don't think you can claim that it's equivalent to type** because then you would have an array of pointers and then the memory wouldn't be contiguous like a type[][] would be. A type[][] would basically boil down to a &type[0][0] and you'd have to access it as a type*.
    So accessing a int array[3][3] as a pointer would be something like: int val = (array + (3*x) + y);

  5. #35
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    22,918
    Then perhaps you have a good explanation of why **array works? As expected, it gets the first value in the array. So if it isn't an array of pointers, then what is 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. #36
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,166
    Then perhaps you have a good explanation of why **array works?
    Array to pointer conversion.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #37
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Elysia View Post
    Then perhaps you have a good explanation of why **array works? As expected, it gets the first value in the array. So if it isn't an array of pointers, then what is it?
    Pass your array to a function that takes a type** and then see what happens when you de-reference it.

  8. #38
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    22,918
    Indeed, it outputs "a":

    Code:
    void foo(char** p)
    {
    	cout << **p;
    }
    
    void Help()
    {
    	char myarray2[10][10] = { { 'a', 'b', 'c' } };
    	foo((char**)myarray2);
    }
    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.

  9. #39
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    Quote Originally Posted by Elysia View Post
    Indeed, it outputs "a":

    Code:
    void foo(char** p)
    {
    	cout << **p;
    }
    
    void Help()
    {
    	char myarray2[10][10] = { { 'a', 'b', 'c' } };
    	foo((char**)myarray2);
    }
    And does
    Code:
    void foo(char** p)
    {
    	cout << p[1][0];
    }
    
    void Help()
    {
    	char myarray2[10][10] = { { 'a', 'b', 'c' }, {'b', 'c', 'd'} };
    	foo((char**)myarray2);
    }
    print "b"? So I think we can safely say that **array doesn't work. Passing in a ** passes a pointer to a pointer; passing in a [][10] passes a pointer to an array. In the first case, when the compiler sees p[1] it advances by the size of what p points to, namely a char * (4 bytes); in the second case, when the compiler sees p[1] it advances by the size of what p points to, namely a char[10] (10 bytes).

  10. #40
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,166
    So I think we can safely say that **array doesn't work.
    That would not be accurate: **array works since when we are dealing with the first of firsts, we can afford to pretend that a scalar type is an aggregate type (and vice versa) even without having additional (otherwise necessary) information.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #41
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    Quote Originally Posted by laserlight View Post
    That would not be accurate: **array works since when we are dealing with the first of firsts, we can afford to pretend that a scalar type is an aggregate type (and vice versa) even without having additional (otherwise necessary) information.
    Right, but only when we are dealing with the first of firsts (or, to be fair, the [0][anything] element).

  12. #42
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    22,918
    Quote Originally Posted by tabstop View Post
    Right, but only when we are dealing with the first of firsts (or, to be fair, the [0][anything] element).
    I'm thinking there seems to be some problems with it. The function didn't work as expected at all.
    It might just be that a 2D array is just a regular pointer. I'm going to have to investigate about this. I'm thinking that since the standard specifies that an array is not a pointer, compiler makers did not have to worry about this.
    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. #43
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Elysia View Post
    I'm thinking there seems to be some problems with it. The function didn't work as expected at all.
    It might just be that a 2D array is just a regular pointer. I'm going to have to investigate about this. I'm thinking that since the standard specifies that an array is not a pointer, compiler makers did not have to worry about this.
    Well just think about how you would implement a real char** instead of a char[][].
    You'd do something like this:
    Code:
    char** pStrArray = malloc( 3 * sizeof( char* ) );
    for ( int i = 0; i < 3; ++i )
    {
        pStrArray[i] = malloc( 3 * sizeof( char ) );
    }
    So the memory layout of that is going to look a lot different than char strArray[3][3];

  14. #44
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    22,918
    Indeed, a 2D array is not type**. Actually, it's still just type*.
    The following works:
    Code:
    void foo(char* p)
    {
    	cout << *p;
    	cout << *(p + 1);
    	cout << *(p + 2);
    
    	cout << *(p + 3);
    	cout << *(p + 4);
    	cout << *(p + 5);
    }
    
    void Help()
    {
    	char myarray2[][3] = { { 'a', 'b', 'c' }, { 'd', 'e', 'f' } };
    	foo((char*)myarray2);
    }
    It shows that they are just, indeed, pointers. It just allocated a contiguous memory space and assigned the pointer to the array.
    While using a pointer like this, we can't use array-like syntax, naturally, because it doesn't know the size of the dimensions.
    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. #45
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,166
    Indeed, a 2D array is not type**. Actually, it's still just type*.
    A 2D array is a 2D array, but being an array it can be converted into a pointer to its first element, which is itself an array.

    EDIT:
    On second thought, it did not make sense: a char* was not a pointer to an array of chars, but a pointer to a char. Then I realised that you were posting C++ code in the C programming forum, and yet used a C-style cast. Your code actually uses a reinterpret_cast, hence you mistook a char[][3] for a char*.
    Last edited by laserlight; 02-05-2008 at 10:42 AM.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Page 3 of 4 FirstFirst 1234 LastLast
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, 02: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, 03:28 PM
  4. code condensing
    By bcianfrocca in forum C++ Programming
    Replies: 4
    Last Post: 09-07-2005, 10: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

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21