Array length

H

Harshal Jain

if I have the code like
int arr[]={1,2,3};
int *arr1=arr;
then how can we get the length of array arr or arr1

I have tried the following but it's of no use :(

int length=0;
while(arr1!=NULL) // or while(*arr!='\0')
{
arr1++;
length++;
}
where length is the length of array.

But this code gives wrong length.
Please help.
 
K

Keith Thompson

Harshal Jain said:
if I have the code like
int arr[]={1,2,3};
int *arr1=arr;
then how can we get the length of array arr or arr1
[...]

Given an array object, you can compute its length like this:

sizeof arr / sizeof arr[0]

Given a pointer to the first element of an array, you cannot compute
the length of the array without more information.
 
P

Prasoon

if I have the code like
int arr[]={1,2,3};
int *arr1=arr;
then how can we get the length of array arr or arr1

I have tried the following but it's of no use :(

int length=0;
while(arr1!=NULL) // or while(*arr!='\0')
{
       arr1++;
       length++;}

where length is the length of array.

But this code gives wrong length.
Please help.

As mentioned by Keith, the length of an array object can be computed
like this

sizeof(arr)/ sizeof(arr[0])

The array in your case is not a NULL terminated array (remember a
string is a NULL terminated array of characters), so there is no use
of " while(arr1!=NULL) ", it will certainly not give you the correct
length of the array.
 
H

Harshal Jain

if I have the code like
int arr[]={1,2,3};
int *arr1=arr;
then how can we get the length of array arr or arr1
I have tried the following but it's of no use :(
int length=0;
while(arr1!=NULL) // or while(*arr!='\0')
{
       arr1++;
       length++;}
where length is the length of array.
But this code gives wrong length.
Please help.

As mentioned by Keith, the length of an array object can be computed
like this

   sizeof(arr)/ sizeof(arr[0])

 The array in your case is not a NULL terminated array (remember a
string is a NULL terminated array of characters), so there is no use
of " while(arr1!=NULL) ", it will certainly not give you the correct
length of the array.

Yeah correct so what should be the termination condition based on
which we can find end of the array (other than string)
 
C

Chris M. Thomasson

if I have the code like
int arr[]={1,2,3};
int *arr1=arr;
then how can we get the length of array arr or arr1
I have tried the following but it's of no use :(
int length=0;
while(arr1!=NULL) // or while(*arr!='\0')
{
arr1++;
length++;}
where length is the length of array.
But this code gives wrong length.
Please help.

As mentioned by Keith, the length of an array object can be computed
like this

sizeof(arr)/ sizeof(arr[0])

The array in your case is not a NULL terminated array (remember a
string is a NULL terminated array of characters), so there is no use
of " while(arr1!=NULL) ", it will certainly not give you the correct
length of the array.

Yeah correct so what should be the termination condition based on
which we can find end of the array (other than string)

You can define you're own:
___________________________________________________________________
#include <stdio.h>

#define MY_ARRAY_TERM -666


int
main(void)
{
size_t i;
int array[] = { 1, 2, 3, 4, 5, 6, 7, MY_ARRAY_TERM };

for (i = 0; array != MY_ARRAY_TERM; ++i);

printf("array has %u elements, plus 1 terminator\n", i);

return 0;
}

___________________________________________________________________




Is that what you are looking for? Or perhaps something like this:
___________________________________________________________________
#include <stdio.h>


#define ARRAY_DEPTH(a) (sizeof(a) / sizeof(*a))


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

printf("array has %u elements\n", ARRAY_DEPTH(array));

return 0;
}

___________________________________________________________________




?
 
K

Keith Thompson

Chris M. Thomasson said:
Yeah correct so what should be the termination condition based on
which we can find end of the array (other than string)

You can define you're own:
___________________________________________________________________
#include <stdio.h>

#define MY_ARRAY_TERM -666


int
main(void)
{
size_t i;
int array[] = { 1, 2, 3, 4, 5, 6, 7, MY_ARRAY_TERM };

for (i = 0; array != MY_ARRAY_TERM; ++i);

printf("array has %u elements, plus 1 terminator\n", i);

return 0;
}


That only works if there's an otherwise unused value that can be used
as a terminator. For strings, '\0' is rare enough in actual data that
using it as a terminator doesn't cause too many problems (though it
*can* be inconvenient sometimes). For an array of ints, depending on
what the values represent, there might be a suitable terminator value.
Is that what you are looking for? Or perhaps something like this:
___________________________________________________________________
#include <stdio.h>


#define ARRAY_DEPTH(a) (sizeof(a) / sizeof(*a))


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

printf("array has %u elements\n", ARRAY_DEPTH(array));

return 0;
}

ARRAY_DEPTH(array) yields a value of type size_t; "%u" expects an
argument of type unsigned int. Use "%zu" if your implementation
supports it (it's a C99ism), or "%lu" with a conversion to unsigned
long.

Also, this method works only with array objects. Arrays are very
often conveyed to functions by passing the address of the first
element, which loses the length information.

Some languages treat arrays as first-class objects, which makes all
this fairly straightforward. C doesn't, with the result that there
are a number of different solutions, none of the ideal.

Note that if you accidentally invoke ARRAY_DEPTH() with a pointer
rather than an array, it will simply give you incorrect results:

#include <stdio.h>

#define ARRAY_DEPTH(a) (sizeof(a) / sizeof(*a))

void func(int array_param[]) {
printf("ARRAY_DEPTH(array_param) = %lu\n",
(unsigned long)ARRAY_DEPTH(array_param)); /* OOPS! */
}

int main(void) {
int array_object[100];
printf("ARRAY_DEPTH(array_object) = %lu\n",
(unsigned long)ARRAY_DEPTH(array_object));
func(array_object);
return 0;
}

Output on my system:
ARRAY_DEPTH(array_object) = 100
ARRAY_DEPTH(array_param) = 1

(The name "array_param" is misleading; it's actually a pointer.)
 
N

Nick Keighley

On Oct 1, 6:29 am, Harshal Jain <[email protected]> wrote:
if I have the code like
int arr[]={1,2,3};
int *arr1=arr;
then how can we get the length of array arr or arr1
I have tried the following but it's of no use :(
int length=0;
while(arr1!=NULL) // or while(*arr!='\0')
{
       arr1++;
       length++;}

why did you think the array would be either null or nul terminated?
As mentioned by Keith, the length of an array object can be computed
like this
   sizeof(arr)/ sizeof(arr[0])

but this trick *won't* work with arr1 as it's a pointer

no it isn't. NULL is a macro that expands to a null pointer constant.
A string is terminated with a null character (sometimes referred to
as
nul). nul is not NULL. In particular the null pointer constant does
not
have to be all bits zero. Yeah wierd I know. Go and read the clc FAQ
for more details.

well it *might* if you were really unlucky. We can't say what it will
do.


don't quote sigs
Yeah correct so what should be the termination condition based on
which we can find end of the array (other than string)

Keith also said this:-
"Given a pointer to the first element of an array, you cannot compute
the length of the array without more information."

There is no way to do what you want. You either tag a special value
onto the end of the array which will never be mistaken for your data,
or (what I'd prefer) carry the length arounf with the array.

void process_stuff (int stuff [], size_t length);

some will say the use of array notation here is confusing.
I don't agree.
 
C

Chris M. Thomasson

Keith Thompson said:
Chris M. Thomasson said:
Yeah correct so what should be the termination condition based on
which we can find end of the array (other than string)

You can define you're own:
___________________________________________________________________
#include <stdio.h>

#define MY_ARRAY_TERM -666


int
main(void)
{
size_t i;
int array[] = { 1, 2, 3, 4, 5, 6, 7, MY_ARRAY_TERM };

for (i = 0; array != MY_ARRAY_TERM; ++i);

printf("array has %u elements, plus 1 terminator\n", i);

return 0;
}


That only works if there's an otherwise unused value that can be used
as a terminator.
Agreed.




For strings, '\0' is rare enough in actual data that
using it as a terminator doesn't cause too many problems (though it
*can* be inconvenient sometimes). For an array of ints, depending on
what the values represent, there might be a suitable terminator value.
Is that what you are looking for? Or perhaps something like this:
___________________________________________________________________
#include <stdio.h>


#define ARRAY_DEPTH(a) (sizeof(a) / sizeof(*a))


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

printf("array has %u elements\n", ARRAY_DEPTH(array));

return 0;
}

ARRAY_DEPTH(array) yields a value of type size_t; "%u" expects an
argument of type unsigned int. Use "%zu" if your implementation
supports it (it's a C99ism), or "%lu" with a conversion to unsigned
long.


DOH! I usually do use '%lu' and cast `size_t' to `unsigned long int', but
obviously failed to do so here!

Ouch!

;^(...


As for C99, well, I don't use it.



Also, this method works only with array objects. Arrays are very
often conveyed to functions by passing the address of the first
element, which loses the length information.

Some languages treat arrays as first-class objects, which makes all
this fairly straightforward. C doesn't, with the result that there
are a number of different solutions, none of the ideal.

Note that if you accidentally invoke ARRAY_DEPTH() with a pointer
rather than an array, it will simply give you incorrect results:

Very good point Sir. I should have pointed that out, but failed to do so.



#include <stdio.h>

#define ARRAY_DEPTH(a) (sizeof(a) / sizeof(*a))

void func(int array_param[]) {
printf("ARRAY_DEPTH(array_param) = %lu\n",
(unsigned long)ARRAY_DEPTH(array_param)); /* OOPS! */
}

int main(void) {
int array_object[100];
printf("ARRAY_DEPTH(array_object) = %lu\n",
(unsigned long)ARRAY_DEPTH(array_object));
func(array_object);
return 0;
}

Output on my system:
ARRAY_DEPTH(array_object) = 100
ARRAY_DEPTH(array_param) = 1

(The name "array_param" is misleading; it's actually a pointer.)

Indeed.



BTW, thank you for taking the time to correct my flawed message Keith!


:^)
 
J

James Kuyper

Debanjan said:
Is the "%lu" is necessary just to avoid the overflow ? Or there is
some other significance of that ?

It's needed because it's undefined behavior to pass printf() a format
specifier and a corresponding argument which do not match. In C90, there
was no format specifier specifically for size_t, and size_t could
potentially be any unsigned integer type. Since, in C90, it was
guaranteed that "unsigned long" was the largest integer type, conversion
of a size_t value to unsigned long was the only approach that was
guaranteed to produce the correct value, of a type for which there was a
guaranteed known format specifier.
 

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,774
Messages
2,569,598
Members
45,152
Latest member
LorettaGur
Top