0

I'm trying to enumerate an array in C (like how in python you can use the #enumerate function).

static enumerate(const char *data[])
{
    int i;
    int stopLength = sizeof(data);
    for(i=0; i < stopLength; i++)
    {
        printf("[%d] %s", i+1, data[i]);
    }
}

int main(int argc, char *argv[])
{
    char *friends[] = {"test", "test", "test"};
    enumerate(friends);
}

However when I try to use this function I get the following error:

utilis.c: In function ‘int enumerate(char**)’:
utilis.c:58:33: warning: ‘sizeof’ on array function parameter ‘data’ will return size of ‘char**’ [-Wsizeof-array-argument]
     int stopLength = sizeof(data);
                                 ^
utilis.c:55:29: note: declared here
 static enumerate(char *data[])
                             ^
utilis.c: In function ‘int main(int, char**)’:
utilis.c:78:46: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
     char *friends[] = {"test", "test", "Test"};
                                              ^
utilis.c:78:46: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
utilis.c:78:46: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]

I understand what the error is telling me, but I don't understand how to implement what I want to do. In python I could do something like this:

friends = ["test", "test", "test"]
for i, f in enumerate(friends, start=1):
    print "[{}] {}".format(i, f)

# [1] test
# [2] test
# [3] test

How can I get my C function to behave as I want it to?

jakehimton
  • 101
  • 8
  • 5
    When you pass an array to a function it decays to a pointer to its first element. Doing `sizeof` on a pointer only returns the size of the actual pointer, and not at what it points to. Therefore when you have functions which needs to iterate over arrays you should always pass along the size (number of elements) as arguments along with the array. – Some programmer dude Mar 28 '17 at 13:53
  • 1
    add the size of your array as a second parameter? – Chris Turner Mar 28 '17 at 13:53
  • 1
    Python's `enumerate` is a _function_, not a keyword. – ForceBru Mar 28 '17 at 13:53
  • 2
    Also note that the compiler aren't give you *errors*, but *warnings*. While warnings will not stop the compiler normally, you should still read them, learn to understand what they mean, and fix the root-cause of them. – Some programmer dude Mar 28 '17 at 13:54
  • @ForceBru Lol, fixed, sorry man. – jakehimton Mar 28 '17 at 13:56
  • @Someprogrammerdude So, pass the size, and the elements, correct? I think I get it thank you. – jakehimton Mar 28 '17 at 13:56
  • 1
    Possible duplicate of [c, finding length of array inside a function](http://stackoverflow.com/questions/17590226/c-finding-length-of-array-inside-a-function) – Sander De Dycker Mar 28 '17 at 14:00
  • @Someprogrammerdude Post that as an answer and I will accept it, thanks man – jakehimton Mar 28 '17 at 14:03
  • Possible duplicate of [Length of array in function argument](http://stackoverflow.com/questions/8269048/length-of-array-in-function-argument) – Persixty Mar 28 '17 at 14:09
  • Your `enumerate` function definition is missing a return type. Looks like `void` would do. – aschepler Mar 28 '17 at 14:21

2 Answers2

1

The problem is that arrays decay to a pointer when passed to functions. In your enumerate function, data is really a pointer of type char **, even though you have declared it as an array – char *[]. There is no way to directly pass whole arrays to functions. The size must be passed additionally either as a parameter, or be contained in a struct, for example.

C arrays do not know their size at runtime. Only when you declare an array (not a pointer) of a static size, you can obtain its size via the sizeof(arr) / sizeof(*arr) expression (evaluated at compile-time):

int arr[42];
/* the result will be equal to `sizeof(int) * 42` */
printf("arr size: %zu\n", sizeof(arr) / sizeof(*arr));

The numerator is the total size of the array in bytes and the denominator is the size of each element, giving you the compile-time size of the array (which cannot change dynamically at runtime).

Blagovest Buyukliev
  • 42,498
  • 14
  • 94
  • 130
1

Since it is a function parameter, an array get adjusted to a pointer to the first element. In your case a pointer to the first pointer in the array. You can't use sizeof on that since that would only yield the size of a pointer, which isn't useful. Instead, you need to pass the size of the array to the function:

static void enumerate(size_t size, const char *data[size])
{
    int i;
    size_t stopLength = size;
    ...

Caller:

enumerate(sizeof(array)/sizeof(*array), array);
Lundin
  • 195,001
  • 40
  • 254
  • 396