-4

Possible Duplicate:
C sizeof a passed array

instead of sending the sizeof:

void main()

    int x[] = {1, 2, 3, 1, 3, 0, 6};
    dupes(x, sizeof x / sizeof x[0]);
...
}

int dupes(int a[], int n)
...
...

why cant i call it with only the array:

int main()
{
    int x[] = {1, 2, 3, 1, 3, 0, 6};
    dupes(x);
...
}
int dupes(int a[])
{
    int n = sizeof a / sizeof a[0];

when i do this the size always gets 1 - and it cant be 1 casue i'm sending an array with 7 elements!

Community
  • 1
  • 1
Sveta26
  • 541
  • 2
  • 8
  • 19
  • 1
    Voting to close and voting down due to Sveta26 copy-pasting the same comment to all answers, seemingly without caring about what the actual answer says. – unwind Jan 03 '12 at 13:27

7 Answers7

3

sizeof is not a function, it a compiler operator (so you don't "call" sizeof, you just use the sizeof operator). The compiler has no way to know the size of the formal argument a for your function dupes (and treat is as int* a, i.e. a pointer formal).

sizeof is always computed at compile time.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • ok so how can i defind it from inside the function and make the call with only the array pointer? – Sveta26 Jan 03 '12 at 13:22
  • You have to give the (runtime) dimension of your array somewhere. How do you give is up to you (as a second parameter, as a conventional constant, as a structure member, in a global variable, ...). The processor don't know what is an array! I strongly suggest to take hours to **read a good C programming book** – Basile Starynkevitch Jan 03 '12 at 13:24
  • 2
    "`sizeof` is always computed at compile time". Always only if no VLA in the sizeof expression. With VLA, if the value of the array size affects the value of the `sizeof` expression, then the array expression is evaluated. – ouah Jan 03 '12 at 13:32
  • @BasileStarynkevitch from C99, in the semantics of the `sizeof` operator: "If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant." – ouah Jan 03 '12 at 13:37
  • @BasileStarynkevitch and with this in 6.7.5.2p4: "Where a size expression is part of the operand of a sizeof operator and changing the value of the size expression would not affect the result of the operator, it is unspecified whether or not the size expression is evaluated." – ouah Jan 03 '12 at 13:42
  • @ouah: Thanks! I learned something... – Basile Starynkevitch Jan 03 '12 at 13:43
1

Arrays decay into a pointer to their first element when they are passed to a function. sizeof only works if you pass the actual original array.

In other languages array references always carry the length along with them but the C philosophy is against this kind of hidden preformance penalty so you have to pass the length yourself.

hugomg
  • 68,213
  • 24
  • 160
  • 246
  • ok so how can i defind it from inside the function and make the call with only the array pointer? – Sveta26 Jan 03 '12 at 13:21
  • @Sveta26: You can't. What you can consider doing is instead of marking the end of input via a separate length attribute you use a special terminator value to mark the last element. This is how they do with strings in the standard library. – hugomg Jan 03 '12 at 13:39
1

This prototype in C:

int dupes(int a[])
{

}

is equivalent to this prototype:

int dupes(int *a)
{

}

You array argument a is converted to a pointer to int.

Regarding function declarators, this appears in 6.7.5.3p7 in C99 standard

A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation.

Arrays in C are second class citizens, you cannot pass arrays to functions. You can just pass a pointer to the first element of the array.

So when you compute sizeof a, the result is the size of the pointer and not the size of the array.

sizeof a / sizeof a[0] in the body of your function actually computes this: sizeof (int *) / sizeof (int) which yields 1 in your system, because the size of an int * is the same as the size of an int in your system.

ouah
  • 142,963
  • 15
  • 272
  • 331
0

sizeof a[0]; retruns the first element of the array

and when you pass an array it returns the address of the first element of the array so you have to specify the length also.

internally traversing an array as follow:

int a[]={1,2,3};

when you pass a[] as a function argument it sends the address of the element a[0] that is internal address of the 1 and calculates a[1] as

address of a[0] + size of int (type of an array)

when you type sizeof(a[]) it will return the sizeof(int pointer) as a[0] contains the internal address(integer pointer).

Hemant Metalia
  • 29,730
  • 18
  • 72
  • 91
  • ok so how can i defind it from inside the function and make the call with only the array pointer? – Sveta26 Jan 03 '12 at 13:20
  • if you know the length of array you can traverse it using pointer but for that `be careful as you are doing the operations with memory` refer http://www.programmersheaven.com/mb/CandCPP/159211/159211/using-a-pointer-to-traverse-the-array-index/ – Hemant Metalia Jan 03 '12 at 13:25
0

It's because when You pass an array to a function, it is copied into a pointer and the information about it's size is lost. In the called function it is just a normal pointer.

So size of (a) becomes 4 (because its a pointer) and sizeof (a[0]) is also 4 (because its an integer), so n equals 1

Sumit Jain
  • 1,484
  • 2
  • 25
  • 44
0

It's because you cannot pass an array directly to a function. You can only pass a pointer to an element within such an array.

In function parameters, the [] does not mean array, it means a pointer

 int dupes(int a[])

is exactly the same as

 int dupes(int *a)

When you use the name of an array as a value, it actually means the pointer to the 1. element in that array. And a pointer is just that, a pointer. It doesn't know it's pointing into an array of a given size.

So e.g. int *a = x; will assign a pointer to the first element in x to a- Same thing when you call a function, dupes(x) will pass a pointer to the first element in x as the argument to the dupes function. This is exactly the same as calling dupes(&x[0])

Inside the dupes() function, its argument is just a pointer. So sizeof x/sizeof x[0] is equivialent to sizeof(int*)/sizeof(int), which is 1 if your pointers are the same size as an int.

(However, since you passed a pointer to the 1. element in an array, you can increment that pointer to access the other elements. e.g. x + 2 will make x point to the 3. element (counting from 1) in that array. And if you dereference that pointer, you get its value: *(x + 2). And remember that as a value, x[2] is the same as *(x + 2)

nos
  • 223,662
  • 58
  • 417
  • 506
  • ok so how can i defind it from inside the function and make the call with only the array pointer? – Sveta26 Jan 03 '12 at 13:21
  • @Sveta26 If you must pass only one argument, the "array", you have to figure out something else. e.g. you could store the size in a global varable which you read inside that function. Or you could store a special value as the last element in the array, e.g. -1, and have the function count how many element it traverse before it finds the -1. – nos Jan 03 '12 at 13:37
0

When an expression of type "N-element array of T" appears in most contexts, it is implicitly converted to an expression of type "pointer to T" and its value is the address of the first element in the array. The only exceptions to this rule occur when the array expression is an operand of the sizeof and unary & operators, or is a string literal being used to initialize an array in a declaration.

When you call dupes, the expression x is converted from type "7-element array of int" to "pointer to int", so the dupes function receives a pointer value, not an array. In the context of a function parameter declaration, T a[N] and T a[] are equivalent to T *a.

So in the dupes function, sizeof a / sizeof a[0] is equivalent to sizeof (int *) / sizeof (int), which in your case is 1.

John Bode
  • 119,563
  • 19
  • 122
  • 198