-1

I have this code where I pass a 1-d array to a function, and try and print it. However, I am not able to print the size of the array inside the function where it's passed.

#include <stdio.h>

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

 /* works */
 printf("size of a==%d\n",sizeof(a));

 fun(a);

 return 0;
}

int fun(int a[])
{
 int i = 0;

 /* does not work */
 printf("size of a==%d\n",sizeof(a));
 for(i=0;i<(sizeof(a)/sizeof(int));i++)
  printf("%d ",a[i]);

 /* works */
 for(i=0;i<10;i++)
  printf("%d ",a[i]);
}

EDIT: How can I calculate the number of elements in the array if I don't want to pass the number of elements as another argument say,

fun(a, sizeof(a)/sizeof(int));

and receive as

int fun(int a[], int n)
{

}
tubby
  • 2,074
  • 3
  • 33
  • 55
  • 3
    Because it decays to a pointer. The size of a statically-allocated array can be determined during compile-time **only within the scope of its declaration** (i.e., inside the function in case of a local array, and inside the file in case of a global array). – barak manos Jun 29 '15 at 22:39
  • 1
    And you have undefined-behavior as the array in the sample does not have 10 elements. – Mahesh Jun 29 '15 at 22:40
  • @barakmanos, how then can I calculate the number of elements in the array if I don't want to pass the number of elements as another argument say, fun(a, sizeof(a)/sizeof(int)); – tubby Jun 29 '15 at 22:41
  • 1
    You can't!!! BTW, `size(a)/sizeof(*a)` is better (keeps you "safe" in case you ever choose to change the type of `a`). The real question here is, why are you inclined to pass it as another argument? You can always declare the array bigger, and pass its size as the first (or last) element, but that would be rather "twisted", let alone, the fact that the type of the array will have to support it (i.e., the **type** will have to be at least as large as `size_t`). – barak manos Jun 29 '15 at 22:41
  • Regarding the "edit", [see here](http://stackoverflow.com/questions/492384/how-to-find-the-sizeofa-pointer-pointing-to-an-array) – M.M Jun 29 '15 at 22:53
  • 1
    The "edit" asks an entirely different question than the original, and has an answer not covered by the duplicate. You may wish to resubmit the "edit" as its own separate question. – user3386109 Jun 29 '15 at 22:58
  • 1
    @barakmanos: The *argument* (the expression between the parentheses in the call) decays to a pointer; there's an implicit array-to-pointer conversion in most contexts. The *parameter* (the object `a` in `int fun(int a[])`) *is* a pointer; in that context, `int a[]` really means `int *a`. – Keith Thompson Jun 29 '15 at 23:04
  • Read section 6 of the [comp.lang.c FAQ](http://www.c-faq.com/). – Keith Thompson Jun 29 '15 at 23:04
  • @user3386109 I reopened the question because the edit did make it a different question. – Iharob Al Asimi Jun 29 '15 at 23:04
  • @KeithThompson that is true and it seems that Java programmers frequently get it wrong. – Iharob Al Asimi Jun 29 '15 at 23:05
  • @KeithThompson: Yes, that's pretty much what I wrote in my comment at the top of this post. I used "it" instead of "the argument", but the term `decay` always refers to a function argument, so I'm not sure why you're telling me this. – barak manos Jun 30 '15 at 04:39

2 Answers2

-1

You can't do it, it's not something that is doable in c, there is a trick though.

Suppose there exists an invalid value, so you can put that value at the end of the array and then to count how many values are in the array you just iterate through the array until you find the invalid value. This is BTW, how strings work in c, and it is also how strlen() calculates the length of a string, so you should avoid multiple calls to strlen() for the same string.

Another way is to use a struct

struct Array 
{
    int  size;
    int *data;
}

You can then write accessor functions to initialize the array, and to set a given value, you will need to use malloc() to allocate memory and point to the allocated block with the data member of the struct.

You can have more members in the struct to make it more sophisticated, like the number of items initialzed/valid in the array and a pointer to the current element too.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
-3

fun could be (theoretically) called from anywhere, so the compiler should not make assumptions about where that a came from, so therefore no assumptions about that size. It is only coincidence that you called them both a, but they could be a and b and still work as they do.

donjuedo
  • 2,475
  • 18
  • 28
  • What question are you answering? – David C. Rankin Jun 29 '15 at 22:45
  • Why what he's doing is not what he meant. (I.e., the question in the title) – donjuedo Jun 29 '15 at 22:46
  • You could have posted the comment as a comment and still have 225 characters left. If others search and find this question looking for an answer -- they get (theoretical prose)?? – David C. Rankin Jun 29 '15 at 22:48
  • He asked why it didn't work the way he wrote it. My answer covers how the size information is not known inside `fun()`. Prose? Really? – donjuedo Jun 29 '15 at 22:50
  • @DavidC.Rankin now they will get a link to duplicate – M.M Jun 29 '15 at 22:52
  • Down vote for a direct answer. It's a tough crowd tonight. – donjuedo Jun 29 '15 at 22:53
  • @donjuedo You mean wrong answer? – Iharob Al Asimi Jun 29 '15 at 23:00
  • Well, I didn't downvote this answer, but I agree it may be a little off the record. Instead, it should explain that arrays passed to functions decay into pointers - that's the real issue here. [I do sense a hostile attitude on SO today too] – Filipe Gonçalves Jun 29 '15 at 23:04
  • @iharob, No, I don't. Your comment led me to review every statement in the answer, and not one of them is wrong. – donjuedo Jun 30 '15 at 01:24
  • @donjuedo Your answer doesn't even make sense. – Iharob Al Asimi Jun 30 '15 at 01:30
  • @iharob, Sure it does. `fun()` is not receiving an object, only a pointer to a scalar array, so there is no dynamic way for `fun()` to determine the size of the `a` it receives. It must be determined at compile time, if at all. The compiler can determine the size of the `a` array in the scope of main -- that's obvious. But inside the scope of `fun()`, the compiler cannot know the size of the array pointed to by that `a`. The OP question, in the title, was "why?", and the shortest answer is, "because the information is not there for use by `fun()`. – donjuedo Jun 30 '15 at 01:49
  • @iharob, You have a very high reputation, so I am surprised you struggle with this. That is not meant to be inflammatory -- I am genuinely puzzled. – donjuedo Jun 30 '15 at 01:50
  • This is the c language, there are no objects involved, although I confess that your comment would work better as an answer than your answer does. It's clear that you do understand what you are talking about, it just seems that you didn't express correctly. The actual problem is indeed that the parameter becomes a pointer inside the function, and the size of a pointer does not depend on what it pointes to. High reputation means nothing, I somtimes give really _dumb_ answers. – Iharob Al Asimi Jun 30 '15 at 01:58
  • @iharob "[I] didn't express correctly" -- I agree wholeheartedly! – donjuedo Jun 30 '15 at 02:07