-
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
-
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 ???
-
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
-
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.
-
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
-
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.
-
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.
-
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
-
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' ;
}
-
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 03:41 PM.
-
> 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.
-
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
-
> 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 05:52 AM.
-
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 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
-
By Michael in forum ASP.NET
Replies: 14
Last Post: 02-24-2006, 08:54 AM
-
By JohnsonGPS in forum C++
Replies: 3
Last Post: 11-16-2005, 06:15 PM
-
By maynard_s in forum Java
Replies: 0
Last Post: 09-06-2005, 02:28 AM
-
Replies: 1
Last Post: 01-02-2001, 04:33 PM
-
By Wade Balzer in forum VB Classic
Replies: 0
Last Post: 06-23-2000, 02: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
Forum Rules
|
Top DevX Stories
Easy Web Services with SQL Server 2005 HTTP Endpoints
JavaOne 2005: Java Platform Roadmap Focuses on Ease of Development, Sun Focuses on the "Free" in F.O.S.S.
Wed Yourself to UML with the Power of Associations
Microsoft to Add AJAX Capabilities to ASP.NET
IBM's Cloudscape Versus MySQL
|
Bookmarks