0

I'm writing a function that is supposed to split a string on "-" and return and array containing the parts from the string, so if the string is: 2017-10-23 I want the array to have three elements populated like: arr[0] = 2017, arr[1] = 10, arr[2] = 23

This is the function:

/* 
 *  return a array of the parts of date_string 
 */
int * to_date_array(char *date_string)
{
        int i = 0;
        int f = 0;
        char *tokens = strtok(date_string, "-"); /* get initial token */
        static int arr[3] = {0, 0, 0};
        char *ptr;
        int val;

        /* init static arr */ 
        for (f = 0; f < sizeof(arr); f++)
                arr[f] = 0;

        /* do the split */
        while (tokens != NULL) {
                val = strtol(tokens, &ptr, 10);
                arr[i++] = val;
                tokens = strtok(NULL, "-");
        }

        /* 
         * for some reason arr becomes 12 elements long?
         * I expected it to have 3 elements
         */
        puts("func: to_date_array");
        puts("------------------------");
        for (f = 0; f < sizeof(arr); f++)
                printf("arr[%d]: %d\n", f, arr[f]);

        return arr;
}

The function works but I'm really puzzled by the "arr" array. I expect it to be three elements long but when I iterate through it and print every element, it show 12 elements?

$ gcc -Wall main.c arguments.c -o timespan 
$ ./timespan 2015-08-10 2017-10-18
func: to_date_array
------------------------
arr[0]: 2015
arr[1]: 8
arr[2]: 10
arr[3]: 0
arr[4]: 0
arr[5]: 0
arr[6]: 0
arr[7]: 0
arr[8]: 0
arr[9]: 0
arr[10]: 0
arr[11]: 0
robnix
  • 15
  • 2

4 Answers4

1

The sizeof operand returns a size in bytes (where by definition a char takes one byte). On your (and mine) machine, sizeof(int) is 4, hence an array of 3 int takes 12 bytes. See nucleon's answer.

Your to_date_array is not reentrant. It would be nicer to return a dynamically allocated array (e.g. with calloc ....). Of course you need then to adopt the convention that its result has to be later free-d (e.g. by the caller).

You could consider also returning a pointer to some struct ending with a flexible array member.

You could also pass arr (and its length) to the to_date_array and have it been filled by that function.

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
1

sizeof computes the size of the array in bytes, thus you have to divide by the size of a single element to get the number of elements, thus use

sizeof(arr)/sizeof(*arr)
nucleon
  • 1,128
  • 1
  • 6
  • 19
1

sizeof returns the number of bytes in the array, not the number of elements. On your system, an int is 4 bytes wide, so the array takes up 12 bytes.

You need to divide the size of the array by the size of a single element to get the number of elements:

sizeof arr / sizeof *arr

C does not do any bounds checking on array access - the array is only three elements wide, but you won't get any sort of OutOfBounds exception if you attempt to access elements outside of that range. The behavior is undefined - your code may crash, it may produce unexpected results, it may work as intended, but the results won't necessarily be repeatable or predictable.

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

sizeof int arr[3] is sizeof(int) * 3 equals to 4*3 = 12

wyc
  • 351
  • 2
  • 11