Integer array length

Hello;
When I wrote a function to print out an array,

void p_array(int arr[])
 {
   int i;
    int size = sizeof(arr) / sizeof(int);
 //    int size = sizeof (arr) / sizeof (arr[0]);
     for (i = 0; i < size; i++)
         printf("%d ", arr);
     printf("\n");
 }

I could only print out the first two elements,( sometimes 8 out of 10 elements). What did I miss?
The problem seems to be the part

size = sizeof arr/sizeof(int);
size = sizeof arr /sizeof arr[0];

My understanding is (copied from stackoverflow):
sizeof returns the size in memory of the passed element. By dividing the size of an array by a single element size, you get the elements count. On the other hand, when counting elements in an array: sizeof(a) / sizeof(a[0]) will still work as well.
But my code does not! I saw this type online quite lot, but mine just does not work (Ubuntu 12.10, 64_bits kernel). Could anyone explain what is wrong with my code? Thanks a lot!

Your array is passed as a pointer. There's no way for your function to know the size of the array, unless you pass that too.

i.e.

void p_array(int arr[], int size) {
 ...
}

A 64-bit pointer (8 bytes) divided by an integer of 4 bytes = 2, which is why you're seeing only two elements.

1 Like

i'll try your code on my machine once i'll get to home but i would rather like to do this by

void p_array(int arr[])
 {
       int *a = arr;
 //    int size = sizeof (arr) / sizeof (arr[0]);
     while(a!=NULL)
        { printf("%d ", *a);a++}

     printf("\n");
 }

You can't.

Thanks everybody!
Scott, what I want is to let my function by itself get the size of the array, especially when the array size is unknown.
Your explanation about "2" is what I thought, but how come sometime it print 8 elements of the array?
I feel it is related to array and pointer/address, but I could not figure it out myself, especially when google gives many discussions, for example, this one. but I am still unclear the problem with my code. Thanks a lot again!

Show us the code that prints 8 elements. An entire program, not just the printing function. If it is an extremely long program, eliminate all non-essentials and construct a minimal case that still prints out 8 elements. Perhaps then, we can provide accurate feedback.

Given what you've shown us, I believe Scott's explanation is as good as it gets. For more info regarding his point, refer to the comp.lang.c FAQ - Question 6.4.

Regards,
Alister

Here is my code, which is for quick sort I am trying to understand each step of the algorithm.

1 #include<stdio.h>

3 void qsort(int[], int, int);
4 void p_array(int[]);

6 int main()
{
8    int i;
9   int array[] = { 55, 66, 32, 12, 9, 73, 2, 4, 37, 36 };
10    int len = sizeof(array) / sizeof(int);
11    for (i = 0; i < len; i++)
12    printf("%d ", array);
    printf("\n");
14    p_array(array);

    qsort(array, 0, len - 1);
17    for (i = 0; i < len; i++)
18    printf("%d ", array);
    printf("\n");
    return 0;

}

 23  void qsort(int a[], int left, int right)
{
    int pivot, l, r, temp;

    l = left;
    r = right;
    pivot = a[(left + right) / 2];

    while (l < r) {
    while (a[l] < pivot) {
        ++l;
34          p_array(a);
    }
    while (a[r] > pivot) {
        --r;
38          p_array(a);
    }
    if (l >= r)
        break;
    temp = a[l];
    a[l] = a[r];
    a[r] = temp;
    ++l;
    --r;
47     p_array(a);
    }
    if (l == r) {
    l++;
51      p_array(a);
   }
    if (left < r) {
    qsort(a, left, l - 1);
55      p_array(a);
    }
    if (l < right) {
    qsort(a, r + 1, right);
59      p_array(a);
    }
60    p_array(a);
}

63 void p_array(int arr[])
{
    int i;
66    int size = sizeof(arr) / sizeof(int);
//    int size = sizeof (arr) / sizeof (arr[0]);
    for (i = 0; i < size; i++)
    printf("%d ", arr);
    printf("\n");
}

I labeled the p_array call for convenience when you point out the problem. I could not understand in the main function line 10, which works fine, but not
line 66.
Output:

55 66 32 12 9 73 2 4 37 36 // this from line 10 ~ 12, which is correct
55 66 
2 4 
...
2 4 
2 4 9 12 32 36 37 55 66 73 // this from line 17 ~ 18 which is also correct 

Why?
By the way, this is NOT an assignment from school, but my self-study. Appreciate any input. Thanks a lot!

For the same reason. The two numbers displayed on each call of p_array() stem from the fact that a[] is an 8-byte pointer and sizeof(int) is 4 bytes, and 8/4 = 2.

So, it's displaying the first two elements of the array as you're sorting it in qsort().

Note that you passed len to qsort(). Why can't you pass it to q_array()?

Thanks Scott!
Yes, I did pass len to p_array, but did not make any difference. Here my focus is about the calculation of the array length.
I could not understand why the calculation of array length in the main function is fine (line 10), but not in the p_array function (line 66). Thanks!

In the main() function it's an array. In the p_array() function it's a pointer to the first element of the array.

I didn't see where you passed len to p_array(), or how it was used there, so I can't comment on it.

Sorry I meant I tried passing len to the p_array function like this:

#include<stdio.h>
void qsort(int[], int, int);
void p_array(int[], int);

int main()
{
    int i;
    int array[] = { 55, 66, 32, 12, 9, 73, 2, 4, 37, 36 };
    int len = sizeof(array) / sizeof(int);
    for (i = 0; i < len; i++)
        printf("%d ", array);
    printf("\n");
    p_array(array, len);
return 0;
}

void p_array(int arr[], int size)
{
    int i;
    size = sizeof(arr) / sizeof(int);
//    int size = sizeof (arr) / sizeof (arr[0]);
    for (i = 0; i < size; i++)
        printf("%d ", arr);
    printf("\n");
}

output:

55 66 32 12 9 73 2 4 37 36 
55 66 

I did not catch the part you said it is an array in the main() but pointer in the p_array(). Seems that's the part I missed. Thanks a lot!

You still have this, which will override the passed variable:

    size = sizeof(arr) / sizeof(int);

Also, as you originally passed len - 1 to qsort(), you'll need to modify the for-loop in p_array to:

    for (i = 0; i <= size; i++)
1 Like

Thanks again! That bug only make small difference. Output:

55 66 32 12 9 73 2 4 37 36 
55 66 32 

I feel understand pointer and array in C (not fluent to use, though!). Could you explain why the two calculations differ?

int len = sizeof(array) / sizeof(int);  //10
int  size = sizeof(arr) / sizeof(int);   //2

Thanks.

I'm not sure where you get 8 from - you'll have to show the code (in context) that produces that number, but passing the length works perfectly fine:

# cat main.c
#include <stdio.h>

int main( int argc, char **argv ) {
  int array[10] = { 3, 6, 9, 12, 15, 18, 21, 24, 27, 30 };
  int i, len = sizeof( array ) / sizeof( int );
  printf( "In main, length of array: %d\n", len );
  printf( "In main, array elements:" );
  for( i = 0; i < len; i++ )
    printf( " %d", array );

  printf( "\n" );
  printf( "\n" );

  showarr_1( array );
  showarr_2( array, 10 );

  return 0;
}
 
int showarr_1( int array[] ) {
  int len = sizeof( array ) / sizeof( int );
  printf( "In showarr_1, length of array: %d (bogus number!)\n", len );
  printf( "\n" );

  return 0;
}
 
int showarr_2( int array[], int len ) {
  int i;
  printf( "In showarr_2, length of array: %d\n", len );
  printf( "In showarr_2, array elements:" );
  for( i = 0; i < len; i++ )
    printf( " %d", array );

  printf( "\n" );

  return 0;
}


# ./main
In main, length of array: 10
In main, array elements: 3 6 9 12 15 18 21 24 27 30

In showarr_1, length of array: 2 (bogus number!)

In showarr_2, length of array: 10
In showarr_2, array elements: 3 6 9 12 15 18 21 24 27 30

edit: you updated your post, to change 8 to 10. It should be clear now why the numbers are different. As previously said: one is an array, the other is a pointer (to the array).

1 Like

Two things still unclear to me:
1) Why the two exact formulas in main() and in showarray_1() get two different number 10 vs 2? That's the part bugs me very much.
2) In your showarray_2(int array[], int len), the local variable len is not calculated. In the main() call, len was called from the main(), that's I want to avoid in the cases when the array length is unknown. I can't provide an example yet.....maybe I am wrong!
It seems I really need read more to get thru this point.
Thank you so much Scott!

Try this:

int arr[32];
int *parr=arr;

printf("sizeof(arr)=%d\n", sizeof(arr));
printf("sizeof(parr)=%d\n", sizeof(parr));

The only time the compiler knows the exact size of the array is when you use it directly. If you pass it around, it becomes a pointer to something of unknown size.

It only knows when you use it directly, because sizeof() is hardcoded. Its value is fixed in stone before the program even runs. You cannot use it in a dynamic way.

2 Likes

the compiler knows the exact size of the array is when you use it directly. Now I got it! Thanks a lot, and thank you, too, Scott!

I'll try.

When a function is called the argument( parameters) for the function are pushed onto the stack. When C was first developed, memory space, and therefore also available stack space, were limited.

When a function is called it is more efficient to pass as a parameter the address of an object than the whole object. It is also faster. They decided that since arrays could be arbitrarily large, it was better to pass the address of the array.

In a 32 bit environment addresses are 32 bits long. int datatypes are usually 32 bit as well. You are confusing:

  1. the address of your array with the physical memory object of the array itself:
    The address is 32 bits, each element of the array is 32 bits because they are the
    the int datatype.
  2. There is nothing in the address of an array or the pointer to the array to tell the
    program how big the array object is.
  3. Because pointers are 32 bits you can print them just like an integer, using "%d".
    Which is wrong. To print a pointer use "%p".
  4. sizeof() gives you the number of bytes of a datatype, all 32 bit pointers are 4 bytes.
void foo(int *arr)
{
    printf("%d ", arr); //WRONG
    printf("%p\n", arr); // correct
    printf("%u %u %u\n", sizeof(arr), sizeof(int *), sizeof(int)); // ALL are the same size
}

int main()
{
    int arr[]={1,2,3,4,5,6,7,8,9,10};
    foo(arr);
    printf("size of arr = %u\n", sizeof(arr));
    return 0;
}

1 Like

As I haven't done any C programming for about 15 years, I'm glad you guys showed up to add better explanations to the matter.

Thanks :slight_smile:

No worry! I should have dove into C 15 years ago, and now I realize C is so important for programming!