sizeof dinamically alocated array....

M

Mateo

I have char *array and it is dinamically alocated....
When I pass it to other function, I need to determine size of this array....
Problem: sizeof operator does not work with dinamically alocated
arrays!?!?!

How can I determine size of dinamically alocated array.... ?


Please advice...
Thx!
 
V

Victor Bazarov

Mateo said:
I have char *array and it is dinamically alocated....
When I pass it to other function, I need to determine size of this
array.... Problem: sizeof operator does not work with dinamically
alocated arrays!?!?!

How can I determine size of dinamically alocated array.... ?

You cannot. You need to store the size at the time of allocation
and pass it into the same function. If you can't do that, do not
use a plain char array, use 'std::string'.

V
 
P

Phlip

Mateo said:
I have char *array and it is dinamically alocated....
When I pass it to other function, I need to determine size of this
array....
Problem: sizeof operator does not work with dinamically alocated
arrays!?!?!

How can I determine size of dinamically alocated array.... ?

This is a Frequently Asked Question, but I don't know if it's in the FAQ.

The answer is you should use an std::vector<> unless you actually need a
primitive array, returned by new[].

If you have a legitimate reason not to use std::vector<>, then pass the size
with the array.

There's no portable way to get this information, because your program is
essentially throwing the information away after the new[] call. Don't.
 
R

red floyd

Phlip said:
The answer is you should use an std::vector<> unless you actually need a
primitive array, returned by new[].

Not to mention that for passing to library/OS routines that require a
naked T*, a std::vector<T> is trivially convertable to a T* by passing
&v[0].
 
B

BobR

Victor Bazarov wrote in message ...
You cannot. You need to store the size at the time of allocation
and pass it into the same function. If you can't do that, do not
use a plain char array, use 'std::string'.
V
--

Well, there's always the 'Three Stooges' method:

size_t SomeFunc( char /* const */ *MyCharArray ){
std::string ForSize( MyCharArray );
size_t ArrSize( ForSize.size() );
// Do something with MyCharArray that needs size.
// don't forget to add 1 if you need to include
// the '\0' at end of array.
return ArrSize;
// size_t ArrSize = sizeof( MyCharArray );
// return ArrSize; // returns 4 (the size of pointer)
}

int main(){
char MyCharArray[] = "abcd1234xyz";
std::cout<<"SomeFunc( MyCharArray ); "
<<SomeFunc( MyCharArray )<<std::endl;
return 0;
}
// output: SomeFunc( MyCharArray ); 11
 
V

Victor Bazarov

BobR said:
Victor Bazarov wrote in message ...
You cannot. You need to store the size at the time of allocation
and pass it into the same function. If you can't do that, do not
use a plain char array, use 'std::string'.
V
--

Well, there's always the 'Three Stooges' method:

size_t SomeFunc( char /* const */ *MyCharArray ){
std::string ForSize( MyCharArray );
size_t ArrSize( ForSize.size() );
// Do something with MyCharArray that needs size.
// don't forget to add 1 if you need to include
// the '\0' at end of array.
return ArrSize;
// size_t ArrSize = sizeof( MyCharArray );
// return ArrSize; // returns 4 (the size of pointer)
}

int main(){
char MyCharArray[] = "abcd1234xyz";
std::cout<<"SomeFunc( MyCharArray ); "
<<SomeFunc( MyCharArray )<<std::endl;
return 0;
}
// output: SomeFunc( MyCharArray ); 11

I believe you've confused the size of the array with the length of
a C string stored in it. Show it again with this 'MyCharArray':

int main() {
char MyCharArray[] = "abc\0def\0ghi\0jkl\0\0\0";
...

V
 
B

BobR

Victor Bazarov wrote in message ...
BobR said:
Victor Bazarov wrote in message ...
Mateo wrote: [snip]
How can I determine size of dinamically alocated array.... ?

You cannot. You need to store the size at the time of allocation
and pass it into the same function. If you can't do that, do not
use a plain char array, use 'std::string'.
V
--

Well, there's always the 'Three Stooges' method:

size_t SomeFunc( char /* const */ *MyCharArray ){
std::string ForSize( MyCharArray );
size_t ArrSize( ForSize.size() );
// Do something with MyCharArray that needs size.
return ArrSize;
}

int main(){
char MyCharArray[] = "abcd1234xyz";
std::cout<<"SomeFunc( MyCharArray ); "
<<SomeFunc( MyCharArray )<<std::endl;
return 0;
}
// output: SomeFunc( MyCharArray ); 11

I believe you've confused the size of the array with the length of
a C string stored in it. Show it again with this 'MyCharArray':

int main() {
char MyCharArray[] = "abc\0def\0ghi\0jkl\0\0\0";
...
V
--

Well, there's always the 'Three Stooges + Mickey Mouse' method: <G>

size_t SomeFunc2( char *MyCharArray ){
std::string ForSize( MyCharArray ); // the Mickey
std::string Look(3, '\0'); // the Mouse
size_t index( ForSize.size() );
while( ForSize.find( Look ) == std::string::npos ){
ForSize.push_back( MyCharArray[index] );
++index;
}
size_t ArrSize( ForSize.size() );
// Do something with MyCharArray.
return ArrSize;
}

int main(){
char MyCharArray[] = "abc\0def\0ghi\0jkl\0\0\0";
std::cout<<"SomeFunc2( MyCharArray ); "
<<SomeFunc2( MyCharArray )<<std::endl;

std::cout<<"sizeof(MyCharArray)/sizeof(*MyCharArray) "
<<sizeof(MyCharArray)/sizeof(*MyCharArray)<<std::endl;
return 0;
}
// -- output --
// SomeFunc2( MyCharArray ); 18
// sizeof(MyCharArray)/sizeof(*MyCharArray) 19

Either:
a - You have no sense of humor.
or
b - I've been had, and I tip my hat to you.
 
A

AnonMail2005

Vector is the way to go.

I have read in Meyers that &v[0] is not advisable unless v.size () > 0.

red said:
Phlip said:
The answer is you should use an std::vector<> unless you actually need a
primitive array, returned by new[].

Not to mention that for passing to library/OS routines that require a
naked T*, a std::vector<T> is trivially convertable to a T* by passing
&v[0].
 
P

Phlip

AnonMail2005 said:
Vector is the way to go.

I have read in Meyers that &v[0] is not advisable unless v.size () > 0.

To the intermediates:

Bow before /C++ Coding Standards : 101 Rules, Guidelines, and Best
Practices/ (C++ in Depth Series) by Herb Sutter & Andrei Alexandrescu. It
covers such scratchy situations as interfacing to a C API that likes raw
pointers.

They advise the &v[0] trick, and I can't recall if they warn about the
size() == 0 situation.

Now I thought that all containers always have a valid .begin() and .end(),
and if they equal then the container is empty, so this might suggest that
&v[0] is always valid (whereas v[0] is not, because it dereferences an
unconstructed object).

So where am I wrong?

To the newbies:

The original poster appeared to be writing their own function that takes a
pointer. If so, they should avoid pointers (as should coders at all levels),
and should pass a reference to a vector:

typedef std::vector<int> ints_type;
void foo(ints_type & ints);

References have fewer features, so they are always better than pointers, and
vectors have more features than arrays, so they are always better than
arrays.

Always pick the technique with fewer features. Or more features. I'll try
again.

Always pick the technique with the safest features. Raw pointers have many
unsafe features, and vectors have many safe ones.
 
T

Tomás

Mateo posted:
I have char *array and it is dinamically alocated....
When I pass it to other function, I need to determine size of this
array.... Problem: sizeof operator does not work with dinamically
alocated arrays!?!?!

How can I determine size of dinamically alocated array.... ?


Please advice...
Thx!


#include <cstddef>
#include <iostream>
using std::cout;
using std::endl;


template<std::size_t i>
void PrintStringLength( char (&str) )
{
cout << "This string is " << (i - 1) << " characters long.\n";
}

int main()
{
char (&str)[7] = * reinterpret_cast< char (*)[7] > ( new char[7] );

std::strcpy(str, "monkey");


PrintStringLength(str);

}


-Tomás
 
A

AnonMail2005

I refer you to the relevant part of the FAQ for the time being since
all of my C++ books are at work:
http://www.parashift.com/c++-faq-lite/containers.html#faq-34.3
AnonMail2005 said:
Vector is the way to go.

I have read in Meyers that &v[0] is not advisable unless v.size () > 0.

To the intermediates:

Bow before /C++ Coding Standards : 101 Rules, Guidelines, and Best
Practices/ (C++ in Depth Series) by Herb Sutter & Andrei Alexandrescu. It
covers such scratchy situations as interfacing to a C API that likes raw
pointers.

They advise the &v[0] trick, and I can't recall if they warn about the
size() == 0 situation.

Now I thought that all containers always have a valid .begin() and .end(),
and if they equal then the container is empty, so this might suggest that
&v[0] is always valid (whereas v[0] is not, because it dereferences an
unconstructed object).

So where am I wrong?

To the newbies:

The original poster appeared to be writing their own function that takes a
pointer. If so, they should avoid pointers (as should coders at all levels),
and should pass a reference to a vector:

typedef std::vector<int> ints_type;
void foo(ints_type & ints);

References have fewer features, so they are always better than pointers, and
vectors have more features than arrays, so they are always better than
arrays.

Always pick the technique with fewer features. Or more features. I'll try
again.

Always pick the technique with the safest features. Raw pointers have many
unsafe features, and vectors have many safe ones.
 
P

Phlip

AnonMail2005 said:
I refer you to the relevant part of the FAQ for the time being since
all of my C++ books are at work:
http://www.parashift.com/c++-faq-lite/containers.html#faq-34.3
Now I thought that all containers always have a valid .begin() and
.end(),
and if they equal then the container is empty, so this might suggest that
&v[0] is always valid (whereas v[0] is not, because it dereferences an
unconstructed object).

Contiguity is a different topic - and yes it permits the &v[0] trick when
..size() > 0. Here's why this is important.

char * foo = new[42];
bar(foo);
// code that might throw
delete[] foo;

To make that more leak-safe, we could wrap foo in a boost::shared_array<> to
make it exception-safe (and take out the delete[] foo). Yet that would leave
foo without the many other benefits of being a vector.

Before a recent revision to The Standard, all vectors were secretely arrays,
so the bar(&foo[0]) trick worked, but The Standard didn't guarantee
contiguity of elements, so the trick was unstable. A program could
conceivably recompile with a version of the Standard Library that didn't
make vectors contiguous, and the compiler would not emit a diagnostic.

My question was whether all containers have a valid .begin() and .end(), and
if so does v[0] fit the rule "you can access one off the end of a container"
even if the container is empty.

Of course live code should just check for size() first (or add a dummy
element, etc.). I'm curious about the language law.
 
A

AnonMail2005

That part of the fact addresses the &v[0] question if you read it in
it's entirety.

v.begin () and v.end (), of course are valid. But you can't
dereference (i.e. access) v.end (). And since v.begin () ==
v.end () for an empty vector, why would you think you could
derefernce v.begin () for an empty vector?
AnonMail2005 said:
I refer you to the relevant part of the FAQ for the time being since
all of my C++ books are at work:
http://www.parashift.com/c++-faq-lite/containers.html#faq-34.3
Now I thought that all containers always have a valid .begin() and
.end(),
and if they equal then the container is empty, so this might suggest that
&v[0] is always valid (whereas v[0] is not, because it dereferences an
unconstructed object).

Contiguity is a different topic - and yes it permits the &v[0] trick when
.size() > 0. Here's why this is important.

char * foo = new[42];
bar(foo);
// code that might throw
delete[] foo;

To make that more leak-safe, we could wrap foo in a boost::shared_array<> to
make it exception-safe (and take out the delete[] foo). Yet that would leave
foo without the many other benefits of being a vector.

Before a recent revision to The Standard, all vectors were secretely arrays,
so the bar(&foo[0]) trick worked, but The Standard didn't guarantee
contiguity of elements, so the trick was unstable. A program could
conceivably recompile with a version of the Standard Library that didn't
make vectors contiguous, and the compiler would not emit a diagnostic.

My question was whether all containers have a valid .begin() and .end(), and
if so does v[0] fit the rule "you can access one off the end of a container"
even if the container is empty.

Of course live code should just check for size() first (or add a dummy
element, etc.). I'm curious about the language law.
 
A

AnonMail2005

I refer you to the relevant part of the FAQ for the time being since
all of my C++ books are at work:
http://www.parashift.com/c++-faq-lite/containers.html#faq-34.3
AnonMail2005 said:
Vector is the way to go.

I have read in Meyers that &v[0] is not advisable unless v.size () > 0.

To the intermediates:

Bow before /C++ Coding Standards : 101 Rules, Guidelines, and Best
Practices/ (C++ in Depth Series) by Herb Sutter & Andrei Alexandrescu. It
covers such scratchy situations as interfacing to a C API that likes raw
pointers.

They advise the &v[0] trick, and I can't recall if they warn about the
size() == 0 situation.

Now I thought that all containers always have a valid .begin() and .end(),
and if they equal then the container is empty, so this might suggest that
&v[0] is always valid (whereas v[0] is not, because it dereferences an
unconstructed object).

So where am I wrong?

To the newbies:

The original poster appeared to be writing their own function that takes a
pointer. If so, they should avoid pointers (as should coders at all levels),
and should pass a reference to a vector:

typedef std::vector<int> ints_type;
void foo(ints_type & ints);

References have fewer features, so they are always better than pointers, and
vectors have more features than arrays, so they are always better than
arrays.

Always pick the technique with fewer features. Or more features. I'll try
again.

Always pick the technique with the safest features. Raw pointers have many
unsafe features, and vectors have many safe ones.
 
P

Phlip

AnonMail2005 said:
v.begin () and v.end (), of course are valid. But you can't
dereference (i.e. access) v.end (). And since v.begin () ==
v.end () for an empty vector, why would you think you could
derefernce v.begin () for an empty vector?

Try this:

assert(0 < v.size() || v.end() == v.begin()); // well defined?

assert(&v[0] == &*v.end()); // not always well defined?

assert(0 < v.size() || &v[v.size()] == v.end()); // always well defined?

So for an empty vector, v.end() == v.begin(), while v[0] is invalid because
v.end() is simply magic - there's no secret contained sequence that it's off
the end of.
 
A

AnonMail2005

The crux of the matter is when it is ok to _dereference_ an iterator.

Your first statement is just iterator comparison - they aren't
dereferenced - so it is safe.

It is not ok to dereference v.end () so *v.end () is not ok. Even if
you do this &*v.end(), so your second statement is not safe.

v[N] where N is an integer is _dereferencing_. So your third statement
is not safe. And neither is v[0] for an empty vector for same reason
as why it is not safe to dereference v.end ().
AnonMail2005 said:
v.begin () and v.end (), of course are valid. But you can't
dereference (i.e. access) v.end (). And since v.begin () ==
v.end () for an empty vector, why would you think you could
derefernce v.begin () for an empty vector?

Try this:

assert(0 < v.size() || v.end() == v.begin()); // well defined?

assert(&v[0] == &*v.end()); // not always well defined?

assert(0 < v.size() || &v[v.size()] == v.end()); // always well defined?

So for an empty vector, v.end() == v.begin(), while v[0] is invalid because
v.end() is simply magic - there's no secret contained sequence that it's off
the end of.
 
A

AnonMail2005

I should have added that your first statement never needs the size
check.

And your third statement is never safe even with the size check.

The crux of the matter is when it is ok to _dereference_ an iterator.

Your first statement is just iterator comparison - they aren't
dereferenced - so it is safe.

It is not ok to dereference v.end () so *v.end () is not ok. Even if
you do this &*v.end(), so your second statement is not safe.

v[N] where N is an integer is _dereferencing_. So your third statement
is not safe. And neither is v[0] for an empty vector for same reason
as why it is not safe to dereference v.end ().
AnonMail2005 said:
v.begin () and v.end (), of course are valid. But you can't
dereference (i.e. access) v.end (). And since v.begin () ==
v.end () for an empty vector, why would you think you could
derefernce v.begin () for an empty vector?

Try this:

assert(0 < v.size() || v.end() == v.begin()); // well defined?

assert(&v[0] == &*v.end()); // not always well defined?

assert(0 < v.size() || &v[v.size()] == v.end()); // always well defined?

So for an empty vector, v.end() == v.begin(), while v[0] is invalid because
v.end() is simply magic - there's no secret contained sequence that it's off
the end of.
 
T

Tomás

Phlip posted:
Tomás said:
delete [] reinterpret_cast< char * > ( &str );

More than enough rope to shoot your foot off, huh? ;-)

Actually I could've just written:

delete [] &str[0];


If you define an array as follows:

char array[70];

Then the following expressions all have unique types:

1: array
Type: char[70]

2: &array
Type: char[70] *

3: array[0]
Type: char

4: &array[0]
Type: char *

( I haven't taken modifiers into account, e.g. "const" )

Beginners tend not to see the distinction because 1, 2 and 4 can all
implicity convert to: char *.

If we define an array of char's with "new", e.g.:

new char[5]

The type of the above expression is not: char[5] *

But rather: char *

Therefore, when calling "delete", it makes sense to give it an expression of
type: char *

rather than: char[5] *

which is why I employed "reinterpret_cast" in my initial post.


Anyway, you could always give the people nice pretty functions:

#include <cstddef>
#include <iostream>
using std::cout;
using std::endl;

template<class T>
class TypeSheath
{
public:
typedef T Actual;
typedef T& Ref;
typedef T* Ptr;
typedef const T* ConstPtr;
};

template<class T, std::size_t i>
T (& NewArray())
{
return * reinterpret_cast< T (*) > ( new T );
}

template<class T, std::size_t i>
void DeleteArray( T (&array) )
{
delete [] &array[0];
}


int main()
{
char (&str1)[15] = NewArray<char,15>();

//Or, if you'd prefer:

TypeSheath<char[15]>::Ref str2 = NewArray<char,15>();

str1[0] = 'H';
str1[1] = 'e';
str1[2] = 'l';
str1[3] = 'l';
str1[4] = 'o';
str1[5] = '\n';
str1[6] = 0;

str2[0] = 'H';
str2[1] = 'e';
str2[2] = 'l';
str2[3] = 'l';
str2[4] = 'o';
str2[5] = '\n';
str2[6] = 0;

cout << str1 << str2;

DeleteArray(str1);
DeleteArray(str2);
}


-Tomás
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,754
Messages
2,569,527
Members
44,998
Latest member
MarissaEub

Latest Threads

Top