problem with sizeof keyword or pointer ?


DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 14 of 14

Thread: problem with sizeof keyword or pointer ?

  1. #1
    Join Date
    Dec 2007
    Posts
    12

    problem with sizeof keyword or pointer ?

    im a newbie to c++ for the most part and its been quite a while since i dabbled with java
    also this is the first time ive ever posted here.
    so plz be patient with my ignorance

    i have a specific problem which i dont understand what in the world is going on
    im trying to pass a char array to a function get its size make a new char array
    and copy its characters useing the char * to the new array

    however as you can see in the below output only half of the string is copyed
    from source to destination and this is confusing to me.

    void main(int argc, char* argv[])
    {
    cout << "Program Start ! \n";
    cout << " \n";

    char mysentence[10] = "blablah";
    MyStrings obj;
    obj.testA(mysentence);
    }

    void MyStrings::testA( char *source ){

    // were going to write this stuff to file
    ofstream myfile ("ExampleLog.txt");
    if (myfile.is_open())
    {

    myfile <<" source = " << source << " size of source= " << ( sizeof(source) ) << " \n";
    cout << " \n";

    char *ptr = new char[ sizeof(source) ];
    // mini func
    int i =0;
    while(i < sizeof(source) ){
    ptr[i] = source[i];

    myfile << " i= "<< i << " \n";
    myfile << "*(ptr + i)= "<< *(ptr+i) << " &ptr= " << &ptr <<" \n";
    myfile << " \n";
    i++;
    }// end this lil bit

    // print it out
    i=0;
    while(i <sizeof(source) ){
    myfile << *(ptr+i) << " ";
    i ++;
    }
    //works
    myfile << " \n";

    delete [] ptr ;


    myfile.close();
    }
    else cout << "Unable to open file";

    }//eofmethod

    NOW THE CRAZY OUTPUT I GET IS THIS

    source = blablah size of source= 4
    i= 0
    *(ptr + i)= b &ptr= 0012FE6C
    i= 1
    *(ptr + i)= l &ptr= 0012FE6C
    i= 2
    *(ptr + i)= a &ptr= 0012FE6C
    i= 3
    *(ptr + i)= b &ptr= 0012FE6C

    b l a b

  2. #2
    Join Date
    Dec 2007
    Posts
    12
    im trying to be clear so the exact thing i dont get is the last line of output
    blab thats only half of what should be in the new char array pointers output
    char *ptr = new char[ sizeof(source) ]; // the output shows its 4 bytes right
    but the source is at least 7 bytes blablah
    which is printed to my log file here
    myfile <<" source = " << source << " size of source= " << ( sizeof(source) ) << " \n";
    cout << " \n";
    i really dont get it am i passing the character array correctly or is something crazy going on with the sizeof keyword cause that log line above << source
    prints out the entire char array which is blablah ???

  3. #3
    Join Date
    Nov 2007
    Posts
    17
    Hi

    In your program output for line
    myfile <<" source = " << source << " size of source= " << ( sizeof(source) ) << " \n"; is 4 byte is correct because source is char pointer having addresses of char array since its have addresses of char array which is int type .

    to copy ur array in other u have to pass starting addresses and its length to function and copy it.



    // arrays as parameters
    #include <iostream>
    using namespace std;

    void printarray (int arg[], int length) {
    for (int n=0; n<length; n++)
    cout << arg[n] << " ";
    cout << "\n";
    }

    int main ()
    {
    int firstarray[] = {5, 10, 15};
    int secondarray[] = {2, 4, 6, 8, 10};
    printarray (firstarray,3);
    printarray (secondarray,5);
    return 0;
    }

    output:------->

    5 10 15
    2 4 6 8 10

  4. #4
    Join Date
    Dec 2003
    Posts
    3,366
    you should use the c++ strings, but if you prefer char arrays there are tools in <cstring> that will help, including strcpy, strlen, and the like.

  5. #5
    Join Date
    Dec 2007
    Posts
    12
    so let me see if i understand this correctly and im sure i dont fully grasp this yet

    the call im making from main obj.testA(mysentence);
    which has the following prototype in the header
    void testA(char *source);
    that is actually going to pass just a memory address of the begining of the array ? which gives me pause, because how does cout know to print the full
    character string inside the method since as you point out i havent passed any
    length information

    also then the real question i have is must i pass a full copy of the character array to the function to extract the length inside the function because this is what i want to do i want the function to act alone to do the copy
    how would i pass a copy of the char array [] or can i do it with a reference?

    btw i definatly dont like the way these char arrays work however the exact problem i have is a api function that requires a char* be passed to the function now i need to be able to change the information in the char array
    it points to on the fly also that information is being modified on the fly
    so i simply want to make my own simple char array when i need to and fill it with anything i need to basically it must be dynamic and must be of type char

    however thank you even with this you put me back on the right track i had forgot that char in c++ is not of type obj like java string

  6. #6
    Join Date
    Dec 2003
    Posts
    3,366
    cout is wired to print chars from an array until it hits a zero (literally, char 0 "null char" or whatever you call it). All of the char array manipulation functions expect this, and they handle it for you, for example
    char str[] = "foo";
    will create an array of size = 4, which contains 'f' 'o' 'o' 0

    strlen and strcpy and all will do that for you, but if you must write it, it would look like this:

    void mystrcpy(char *src, char*dest)
    {
    int i = 0;
    while(src[i++]) //stops when it finds that magic zero i mentioned
    dest[i] = src[i];
    }

    The thing you seem to be asking, but not directly, I will answer now:
    the name of an array is a pointer to the memory of that array, location zero. You cannot easily pass an array by value, the language trys to outsmart you and pass by pointer(reference). You do not need oddness when passing arrays around, such as &str or char** arguments, because of this language feature the pass by reference is already covered and you just call mystrcpy(arrayname, whatever).

    c++ has an object string, its very nice. char array is from C and is occasionally handy for non-text things like an array of raw bytes for sending over a network or the like.

  7. #7
    Join Date
    Dec 2003
    Posts
    3,366
    by the way there are advantages to the way the char arrays work. They predate the entire concept of object oriented programming and a lot of thought was put into them, so while they seem clunky *now* at the time they were fairly streamlined for speed & a relatively easy to use interface.

  8. #8
    Join Date
    Dec 2007
    Posts
    12
    jonnin i thank you
    that pretty much answered all of my present questions
    and im not opposed to useing those functions the cout question was more of
    a after thought in response to the previous question and its always nice to
    know how things work

  9. #9
    Join Date
    Dec 2007
    Posts
    401
    if the array is not allocated dynamically (number of elements is a constant known at compile time), you could also pass an argument of type 'reference to array'. eg.
    Code:
    #include <cstddef>
    #include <iostream>
    
    // return number of elements in an array
    template< typename T, std::size_t N > inline
    std::size_t size( T(&a)[N] ) // arg is reference to array of N elements
    { return N ; }
    
    int main()
    {
      char cstr[] = "a c style string" ;
      double numbers[10] ;
      std::cout << size(cstr) << '\t' << size(numbers) << '\n' ;
    }

  10. #10
    Join Date
    Dec 2007
    Posts
    12
    thanks but i actually have'nt attempted to get into templates yet when i look
    at them my eyes spin in circles :)

    i definatly intend for the array to be dynamic
    because i intend to use the same char pointer in one method
    that is passed to a api function
    however the info passed in will be lines of text that are constant yet
    thier will have to be int values that are changing that will need to be
    printed out so basically im going to have a single char array get made
    and delteted as needed yet keep the same pointer to pass to the function
    yes i could make a really big constant char array but lets say i want to print
    no more than a line most of the time then only during a slow down or msg
    in the program a huge paragraph no sence in keeping that huge char array
    if i just go back to a line for another 5 minutes or if i dont need the printout
    function going at all at the time

    incedently this is all basically just learning for me i do it slowly and one step at a time its not my job just a hobby and the problem arose outputing text
    to a directx text function however i put the problem itself into a console app
    to understand it which is rewritten below i really enjoy learning c++

    Code:
    void MyStrings::testA( char *source ){
    
        // were going to write this stuff to fil
        ofstream myfile ("ExampleLog.txt");
        if (myfile.is_open()){
    	
    	myfile <<" source = " << source << "  sizeof(source)= " << ( sizeof(source) ) << " strlen(source)= " << strlen(source) << "   \n";
    
    	char *ptr = new char[ strlen(source)+1 ];// the new char array
    	
    	// mini func loop here do the lil copy
    	int i =0;
    	while(i < strlen(source)+1 ){ // one possible problem is what if theirs no null character can i rely on strlen to detect that
                  ptr[i] = source[i];
    	  myfile << "\n i= " << i << "  \n *(ptr + i)= "<< *(ptr+i) << "        &ptr+i= " << &ptr+i <<" \n";
    	  i++;
    	}// end this lil loop
    
    	 // print out new array
    	myfile << "\n new char array printout array +1 \n";
    	i=0;
    	while(i < strlen(source)+1 ){
                   myfile << *(ptr+i) << " ";
    	  // make sure i can find the null value
    	  if( *(ptr + i) == 0 ){ myfile << "\n  0 has been detected in new *p array at i = " << i << "  \n"; 
    	  }
    	  i ++;
    	}
    
        // print out original array
    	myfile << "\n source char array printout array +1 \n";
    	i=0;
    	while(i < strlen(source)+1 ){ 
                   myfile << *(source+i) << " ";
    	  // make sure i can find the null value 0
    	  if( source[i] == 0  ){ myfile << "\n  0 has been detected in source array at i = " << i << "  \n"; 
    	  }
    	  i ++;
    	}
    
        delete [] ptr ;
    
         myfile.close();
    	}
        else cout << "Unable to open file";
    
    }//eofmethod
    and the above gives the output below
    Code:
    source = blablah  sizeof(source)= 4 strlen(source)= 7   
    
     i= 0  
     *(ptr + i)= b        &ptr+i= 0012FE6C 
    
     i= 1  
     *(ptr + i)= l        &ptr+i= 0012FE70 
    
     i= 2  
     *(ptr + i)= a        &ptr+i= 0012FE74 
    
     i= 3  
     *(ptr + i)= b        &ptr+i= 0012FE78 
    
     i= 4  
     *(ptr + i)= l        &ptr+i= 0012FE7C 
    
     i= 5  
     *(ptr + i)= a        &ptr+i= 0012FE80 
    
     i= 6  
     *(ptr + i)= h        &ptr+i= 0012FE84 
    
     i= 7  
     *(ptr + i)=          &ptr+i= 0012FE88 
    
     new char array printout array +1 
    b l a b l a h   
      0 has been detected in new *p array at i = 7  
    
     source char array printout array +1 
    b l a b l a h   
      0 has been detected in source array at i = 7
    apperantly i havent mastered the code tags either looks better in my
    compiler
    Last edited by xlightwavex; 12-08-2007 at 04:41 PM.

  11. #11
    Join Date
    Dec 2007
    Posts
    401
    > one possible problem is what if theirs no null character can i rely on strlen to detect that
    no. strlen will count the number of bytes upto a null character; the null character is required.
    if you are using c-style strings (arrays of char), it is a good idea to null terminate them. almost all the c library functions require that. you could just allocate space for one extra null character at the end. things would work out much easier.

    if for some reason, that is not feasible, you could think of using a struct
    Code:
    struct my_array
    {
       std::size_t sz ; // length of data
       char* data ;
    };
    to copy the array, you do not need to write a loop that copies element by element. strcpy copies null terminated strings; memcpy can copy arrays of any pod type.

  12. #12
    Join Date
    Dec 2007
    Posts
    12
    well i was going to let it die it seems to be slowly straying off topic but from the above post
    3 questions?
    1)
    define arrays of any POD type ? im not familiar with the term
    2)
    is their a string concantation function "sorry if i mispelled it"
    3)
    although this is off topic and i probably wouldnt try to use the struct
    how is that above structure used
    i have never actually used structures only browsed over in reading
    char *data is a memory address of arrays begining?
    i guess that std::size_t sz ; is the length of the data so that i can use it
    in say my own string structure ? im a lil confused on that line so i can grab
    the length myself ?
    why the std::size_t how does that work
    i might as well soak up all the info i can.

    half of this stuff is not even in either of my c++ books

  13. #13
    Join Date
    Dec 2007
    Posts
    401
    > define arrays of any POD type ? im not familiar with the term
    very briefly, A POD type is a C++ type that has an equivalent in C, and that uses the same rules as C uses for initialization, copying, layout, and addressing.
    for more information, see http://www.parashift.com/c++-faq-lit....html#faq-26.7

    > is their a string concantation function
    yes, the ISO C library has two of them:
    char * strcat( char* dest, const char* srce ) ; for null terminated strings
    char * strncat( char* dest, const char* srce, size_t N ) ; srce need not be null terminated, but dest must be.

    > why the std::size_t how does that work
    size_t in C or std::size_t in C++ is the type of the value returned by 'sizeof' operator.
    it is a typedef for some suitable unsigned integral type which can be used to hold the size of any object in a C/C++ program. as an array in C/C++ is an object itself, this type can also be used to store the size of an array. (this typedef is required for portability reasons.)

    > how is that above structure used
    when a c-style array is dynamically allocated, the member sz is used to store the size of the array and the member data is a pointer to the first element. the struct is used to just keep these two pieces of information together in one place. for example:
    Code:
    #include <iostream>
    #include <cstring>
    
    struct my_array
    {
       std::size_t sz ; // length of data
       char* data ;
    };
    
    my_array construct( const char* cstr /* null terminated */ )
    {
      std::size_t n = std::strlen(cstr) ;
      my_array a = { n, new char[n] };
      std::memcpy( a.data, cstr, n ) ;
      return a ;
    }
    
    my_array clone( const my_array& a )
    {
      my_array b = { a.sz, new char[a.sz] };
      std::memcpy( b.data, a.data, b.sz ) ;
      return b ;
    }
    
    my_array cat( const my_array& a, const my_array& b )
    {
      my_array c = { a.sz + b.sz, new char[a.sz+b.sz] };
      std::memcpy( c.data, a.data, a.sz ) ;
      std::memcpy( c.data+a.sz, b.data, b.sz ) ;
      return c ;
    }
    
    void print( const my_array& a )
    {
      for( std::size_t i=0 ; i<a.sz ; ++i )
        std::cout << a.data[i] ;
    }
    
    int main(int argc, char** argv)
    {
      my_array hello = construct( "hello " ) ;
      my_array world = construct( "world!" ) ;
      my_array hello_world = cat( hello, world ) ;
      print( hello ) ;
      std::cout << " + " ;
      print( world ) ;
      std::cout << " == " ;
      print( hello_world ) ;
      std::cout << '\n' ;
    }
    in practice, a c++ programmer would use a std::string instead of a home-grown structure of this kind.
    Last edited by vijayan; 12-09-2007 at 06:52 AM.

  14. #14
    Join Date
    Dec 2007
    Posts
    12

    Smile

    If your array is statically allocated, then you can use
    Code:
    char array[50];
    
    Count = sizeof(array)/sizeof(array[0]);
    This works for almost all native type arrays (as long as they are allocated on stack).

    In fact there is a macro called
    Code:
    _countof(x)
    that does the same for you.

    Typically its defined as
    Code:
    #define _countof(x)    ( (sizeof(x)) / (sizeof(x[0])))
    However, this trick doesnt work for dynamically allocated arrays (such as those allocated with new operator or malloc function. For dynamic arrays, you need to explicitly maintain a sentinel at the end of array to identify the limits and there by its size.

    All the best.

    Yours,
    Palem Gopalakrishna http://www.geocities.com/krishnapg/

Similar Threads

  1. a very weird problem (AGAIN!!!)
    By Michael in forum ASP.NET
    Replies: 14
    Last Post: 02-24-2006, 09:54 AM
  2. Replies: 3
    Last Post: 11-16-2005, 07:15 PM
  3. Replies: 0
    Last Post: 09-06-2005, 03:28 AM
  4. pointer problem
    By DevX in forum .NET
    Replies: 1
    Last Post: 01-02-2001, 05:33 PM
  5. Replies: 0
    Last Post: 06-23-2000, 03:17 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center