-2

I am writing a function separate from main that reads in an array of structs and prints each array element's struct elements. My problem however is the condition statement for looping though this array to print each element. sizeof(a)/sizeof(a[]) just doesnt work in the function because it is equal to zero within the prototype. Is there something i am missing? I've tried pointer arithmetic and it does not work either.

void printNames( person a[]){

    int i;

    for(i = 0;i<sizeof(a)/sizeof(a[0]);i++)
        printf("Name: %s | Age: %d\n", a[i].name, a[i].age);

}

int main(int argc, char *argv[]){

    if (argc == 1 || argc%2 == 0){
        printf("Invalid arguments.\n Usage: %s name1 age1 name2 age2 ...", argv[0]);
        return 0;
    }

    printf("You have entered %d person(s) into the program.\n", argc/2);
    person people[argc/2];

    int i;

    for (i = 0; i<argc/2;i++){
        strcpy(people[i].name, argv[i*2+1]);
        people[i].age = atoi(argv[i*2+2]);

    if(people[i].age <= 0){
        printf("Invalid age <= 0. Try again.");
        return 0;
    }


}
James
  • 176
  • 1
  • 4
  • 16
Flower
  • 381
  • 1
  • 6
  • 17
  • 1
    Show us the minimal code. – mazhar islam Jun 24 '15 at 02:58
  • 6
    arrays decay to pointers when passed as an argument so `sizeof(a)` is the size of a pointer to `a`, not the array. You'll need to pass the length of the array explicitly, [see here](http://stackoverflow.com/questions/9413046/how-to-get-the-length-of-array-in-c-is-sizeof-is-one-of-the-solution). – ryanpattison Jun 24 '15 at 03:06
  • In addition to what rpattiso said, notice you cannot declare an array in C using `person people[argc/2]` because `argc` is a variable. Arrays in which the size is not known at compile time must be allocated with `malloc()`. The macro `sizeof()` is also ran at compile time at will not be able to figure out the size of dynamically allocated arrays, you have to keep track of your array size in some other way. – Havenard Jun 24 '15 at 03:58
  • 1
    @Havenard `person people[argc/2]` is VLA . VLA can use since C99. also sizeof isn't macro. sizeof also work for VLA (at run time). – BLUEPIXY Jun 24 '15 at 09:56

2 Answers2

2

a becomes a pointer when passed as parameter to a function, so it cannot figure out the size of the array just from having this pointer, you have to inform the function about its size:

void printNames(person *a, size_t num)
{
    int i;
    for (i = 0; i < num; i++)
        printf("Name: %s | Age: %d\n", a[i].name, a[i].age);
}

Then call printNames from main like this:

printNames(people, sizeof(people)/sizeof(*people));
Havenard
  • 27,022
  • 5
  • 36
  • 62
Jaimy
  • 227
  • 1
  • 8
1

In C, array parameters are decayed into pointers. So, the expression sizeof(a)/sizeof(a[0]) becomes sizeof(int *)/sizeof(int) which results in 1 (assuming the size of int and int * is 4) and hence the for loop within the printNames() is executed only once regardless of the size of the array.

Therefore, sizeof shouldn't be used to obtain the number of elements in these cases. Instead, we can pass an additional parameter for array size to printNames().

Consider the following C program:

#include<stdio.h>
void func(int array[])  
{
  int i;   
  int arraySize = sizeof(array)/sizeof(array[0]); /* arraySize <-- 1<-- 4/4 */
  for (i = 0; i < arraySize; i++) 
  {  
    array[i] = i; 
  }
}

int main()
{
  int i;  
  int array[4] = {0, 0 ,0, 0};
  func(array);

  for(i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
    printf(" %d " ,arr[i]);

  getchar();  
  return 0;
}    

Output: 0 0 0 0 on a Intel Architecture-32 machine.

So the corrected program is:

#include<stdio.h>
void func(int array[], size_t arraySize)  
{
  int i;   
  for (i = 0; i < arraySize; i++) 
  {  
    array[i] = i;  
  }
}

int main()
{
  int i;  
  int array[4] = {0, 0 ,0, 0};
  func(array, 4);

  for(i = 0; i < sizeof(array)/sizeof(array[0]); i++)
    printf(" %d ", array[i]);

  getchar();  
  return 0;
}    
TryinHard
  • 4,078
  • 3
  • 28
  • 54
  • 1
    @Flower: `sizeof(myarray)/sizeof(myarray[0])` is a perfectly appropriate thing to do ... *WITH THE ORIGINAL ARRAY* (here, "people"). If you took the length *outside* of printNames(), like would be good. But, as Tryin correctly pointed out, "the array reference decays to a pointer" *inside* of printNames(). A common solution would be to add an "int length" argument to printNames, for example: `printNames(people, sizeof(people)/sizeof(people[0]);`. – paulsm4 Jul 09 '15 at 05:58