Help with sizeof and pointers

M

Metzen

hello,
ok, I want to find the length of an int array that is being passed to a function:

main()
{
int array[]={1,2,3,4,5,6,7,8};
function(array);
}
function(int *array)
{
int arraylen = sizeof(*array)/sizeof(int);
}


arraylen should be 8 I get 1.

What am I doing Wrong?

Thanx
 
K

Kevin Goodsell

Metzen said:
hello,
ok, I want to find the length of an int array that is being passed to a function:

You can't pass an array to a function, at least not directly.

int main()

There is no "implicit int" rule in C++, and there hasn't been for many
years.
{
int array[]={1,2,3,4,5,6,7,8};
function(array);

This passes a pointer to the function.
}
function(int *array)

'array' is a somewhat misleading name for a pointer.
{
int arraylen = sizeof(*array)/sizeof(int);

sizeof(*array) == sizeof(int), so of course you get 1 here. But no
matter what you do, you won't get the size of the memory pointed to by
'array' using sizeof.
}


arraylen should be 8 I get 1.

What am I doing Wrong?

You need to pass the size into the function.

-Kevin
 
S

Steven C.

You have two choices either end your array with a unque int or pass the
size.

main()
{
int array[]={1,2,3,4,5,6,7,8};
function (array, sizeof(array)/sizeof(int))
}

function(int *array, int size)
{
}



hello,
ok, I want to find the length of an int array that is being passed to a
function:

main()
{
int array[]={1,2,3,4,5,6,7,8};
function(array);
}
function(int *array)
{
int arraylen = sizeof(*array)/sizeof(int);
}


arraylen should be 8 I get 1.

What am I doing Wrong?

Thanx
 
J

Jon Bell

hello,
ok, I want to find the length of an int array that is being passed to a
function:

You can't. You have to pass in the length as a separate
argument/parameter.
main()
{
int array[]={1,2,3,4,5,6,7,8};
function(array);
}
function(int *array)
{
int arraylen = sizeof(*array)/sizeof(int);
}


arraylen should be 8 I get 1.

What am I doing Wrong?

You're using arrays instead of vectors.

#include <vector>

using namespace std;

void function (vector<int>& array)) // functions in C++ must have
// return types
{
int arraylen = array.size();
}

int main () // according to the C++ standard, main() must return an int.
{
vector<int> array(8);
array[0] = 1;
array[1] = 2;
// etc.
function (array);
return 0;
}
 
?

=?iso-8859-1?Q?Juli=E1n?= Albo

Metzen escribió:
ok, I want to find the length of an int array that is being passed to afunction:

main()
{
int array[]={1,2,3,4,5,6,7,8};
function(array);
}
function(int *array)
{
int arraylen = sizeof(*array)/sizeof(int);
}

arraylen should be 8 I get 1.

What am I doing Wrong?

You are using sizeof (*array), * array is equivalent in this case to
array [0], that is, an int, then you are dividing sizeof (int) by sizeof
(int).

You need something like sizeof (array) / sizeof (int), if what you
intend is obtain the number of elements in the array. Or better yet,
sizeof (array) / sizeof (* array), that will no require change if you
later change your mind and use an array of double, for example.

Regards.
 
B

Big Brian

You need to pass the size into the function.


Or, if you can make some assumptions about the array, like what's the
last value in it ( like '\0' terminated c style char arrays ), you can
determine the length of the array.

-Brian
 
?

=?iso-8859-1?Q?Juli=E1n?= Albo

Julián Albo escribió:
main()
{
int array[]={1,2,3,4,5,6,7,8};
function(array);
}
function(int *array)
{
int arraylen = sizeof(*array)/sizeof(int);
}

arraylen should be 8 I get 1.

What am I doing Wrong?

You are using sizeof (*array), * array is equivalent in this case to
array [0], that is, an int, then you are dividing sizeof (int) by sizeof
(int).

You need something like sizeof (array) / sizeof (int), if what you
intend is obtain the number of elements in the array. Or better yet,
sizeof (array) / sizeof (* array), that will no require change if you
later change your mind and use an array of double, for example.

Ops, I don't see you passed array to a function. In that case sizeof
array will give you the size of a pointer, not the size of the array.

Regards.
 
B

Buster

Metzen said:
hello,
ok, I want to find the length of an int array that is being passed to a
function:

The following might work. I can't work out whether the standard says it does.

// Begin listing
#include <iostream>
#include <ostream>

#define MACRO(a) (sizeof (a) / sizeof (int))

template <typename T, unsigned N>
int function (T (&) [N]) { return N; }

int test (int a [])
{
// std::cout << function (a) << ", "; // compile-time error
std::cout << MACRO (a) << std::endl; // no error signaled
}

int main ()
{
int array [] = { 1, 2, 3, 4, 5, 6, 7, 8 };

std::cout << function (array) << ", ";
std::cout << MACRO (array) << std::endl;

test (array);
}
// End listing

I get what I expected on mingw32-g++ 3.2 and on bcb32:
the output is "8, 8"; "1". Both compilers report the compile
time error marked if I uncomment that line.

So the template version is slightly superior in that, although
it only works in a small set of situations, it will not compile
unless it can give you the correct answer.

It's probably only rarely that this can be used instead of the
techniques mentioned in the other replies, and even more
rarely that it will provide any significant advantage in speed
or code size. But maybe sometimes.

Yours,
Buster.
 
S

Shane Beasley

function(int *array)
{
int arraylen = sizeof(*array)/sizeof(int);

That's the size of a pointer divided by the size of the object to
which it points, the result of which is meaningless.
}


arraylen should be 8 I get 1.

What am I doing Wrong?

You're passing a pointer, not an array. Technically, in modern C++,
you can fix the problem by passing an array by reference like this:

#include <cstddef>

// the size of an array is most properly represented by std::size_t
template <std::size_t N>
void function (int (&array) [N]) {
std::size_t arraylen = N;
}

However, that most people don't write functions like this. Rather,
they just pass in the size themselves:

void function (int *array, std::size_t arraylen) { }
function(array, sizeof(array) / sizeof(array[0]));

Perhaps you can combine the approaches:

template <typename T, std::size_t N>
std::size_t size (T (&) [N]) { return N; }
template <typename T, std::size_t N>
std::size_t size (const T (&) [N]) { return N; }
function(array, size(array));

- Shane
 
D

Duane Hebert

// Begin listing
#include <iostream>
#include <ostream>

#define MACRO(a) (sizeof (a) / sizeof (int))

template <typename T, unsigned N>
int function (T (&) [N]) { return N; }

int test (int a [])
{
// std::cout << function (a) << ", "; // compile-time error
std::cout << MACRO (a) << std::endl; // no error signaled
}

int main ()
{
int array [] = { 1, 2, 3, 4, 5, 6, 7, 8 };

std::cout << function (array) << ", ";
std::cout << MACRO (array) << std::endl;

test (array);
}
// End listing

I get what I expected on mingw32-g++ 3.2 and on bcb32:
the output is "8, 8"; "1". Both compilers report the compile
time error marked if I uncomment that line.

So the template version is slightly superior in that, although
it only works in a small set of situations, it will not compile
unless it can give you the correct answer.

It's probably only rarely that this can be used instead of the
techniques mentioned in the other replies, and even more
rarely that it will provide any significant advantage in speed
or code size. But maybe sometimes.



What happens if you do:
int main ()
{
short array [] = { 1, 2, 3, 4, 5, 6, 7, 8 };
std::cout << MACRO (array) << std::endl;
}

What if short was SomeLargeObect instead? Stroustrup advises against using
macros as they defeat the
type safety that C++ supplies. I would suggest that the template solution
is more than "slightly" superior in
that respect.
 
K

Kevin Goodsell

Big said:
Or, if you can make some assumptions about the array, like what's the
last value in it ( like '\0' terminated c style char arrays ), you can
determine the length of the array.

True. That's sort of passing the size in implicitly. Passing a
std::vector (probably by reference) instead is another obvious solution,
which I didn't mention mostly because I was in a hurry. But that also
passes the size (implicitly) into the function. My statement is quite
true, but has to be taken in a very broad sense. Somehow, information
about where the array ends must be communicated to the function (and
it's not implicit in an "array argument" which is, in fact, not an array
at all).

-Kevin
 
K

Kevin Goodsell

Buster said:
function:

The following might work. I can't work out whether the standard says it does.

It absolutely will not work.
// Begin listing
#include <iostream>
#include <ostream>

#define MACRO(a) (sizeof (a) / sizeof (int))

template <typename T, unsigned N>
int function (T (&) [N]) { return N; }

int test (int a [])

The type of a is 'pointer to int'.
{
// std::cout << function (a) << ", "; // compile-time error

This didn't work because 'a' is not an array, but a pointer. You CANNOT
pass arrays to functions (directly). It always passes a pointer. Array
arguments... aren't. They are pointer arguments.
std::cout << MACRO (a) << std::endl; // no error signaled

The macro expands to

(sizeof (a) / sizeof (int))

which is equivalent to (sizeof(int*)/sizeof(int)) which does not give
the number of elements pointed to by 'a'.

I see that later you say this is the result you expected. OK, then...
but it's not an answer to the question, because it doesn't let you
determine the size of an array pointed to by a pointer argument to a
function.

-Kevin
 
B

Buster

Kevin Goodsell said:
does.

It absolutely will not work.

I think we're in agreement about what does and doesn't work. What I expected
to happen, happens. What I'm not sure of is whether what I expect is enforced
by the standard.
This didn't work because 'a' is not an array, but a pointer. You CANNOT
pass arrays to functions (directly). It always passes a pointer. Array
arguments... aren't. They are pointer arguments.

Yes, I know.
The macro expands to

(sizeof (a) / sizeof (int))

which is equivalent to (sizeof(int*)/sizeof(int)) which does not give
the number of elements pointed to by 'a'.

Yes, I know. I recommended the template solution and showed
the older C-style technique for comparison. It's unfortunate that
I got the macro wrong, but there you go.
I see that later you say this is the result you expected. OK, then...
but it's not an answer to the question, because it doesn't let you
determine the size of an array pointed to by a pointer argument to a
function.

The question was "I want to find the length of an int array that is being
passed to a function". No mention of pointers there.
 
B

Buster

Duane Hebert said:
What happens if you do:
int main ()
{
short array [] = { 1, 2, 3, 4, 5, 6, 7, 8 };
std::cout << MACRO (array) << std::endl;
}

Implementation specific. But I should have had:
#define MACRO(a) (sizeof (a) / sizeof * (a))
which works in that situation.
What if short was SomeLargeObect instead?

The new MACRO would work just fine.
Stroustrup advises against using
macros as they defeat the
type safety that C++ supplies.

Quite right too, but type safety is not the issue here.
The decay of an array into a pointer is what makes
this macro dangerous.
I would suggest that the template solution
is more than "slightly" superior in
that respect.

"Slightly" is enough for me.

Thanks,
Buster.
 
A

Artie Gold

Buster said:
I think we're in agreement about what does and doesn't work. What I expected
to happen, happens. What I'm not sure of is whether what I expect is enforced
by the standard.




Yes, I know.




Yes, I know. I recommended the template solution and showed
the older C-style technique for comparison. It's unfortunate that
I got the macro wrong, but there you go.




The question was "I want to find the length of an int array that is being
passed to a function". No mention of pointers there.
You may be passing an array, but by the time the function you're
calling sees it, it has decayed into a pointer.

HTH,
--ag
 
B

Buster

The question was "I want to find the length of an int array that is being
You may be passing an array, but by the time the function you're
calling sees it, it has decayed into a pointer.


Not if you pass the array by reference.

Regards,
Buster.
 

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

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top