15

I'm wanting to pass an array into a function. From what I can see, there are 2 ways of doing this:

1.

void f (int array[]) {
    // Taking an array with square brackets
}

2.

void f (int *array) {
    // Taking a pointer
}

Each one is called by:

int array[] = {0, 1, 2, 3, 4, 5};
f (array);

Is there any actual difference between these 2 approaches?

Luke
  • 2,038
  • 3
  • 22
  • 46
  • 6
    This must have been asked multiple times, but it's really hard to find a duplicate for some reason. The answer is "there's no difference". – Sergey Kalinichenko Jun 11 '17 at 23:56
  • @dasblinkenlight, yeah, it seems like a basic question. I've looked around, but haven't found a clear answer for it. – Luke Jun 11 '17 at 23:57
  • @dasblinkenlight, "parsing" is the correct word to use, not "passing": see this [definition](https://www.google.com/search?client=ubuntu&channel=fs&q=define+parse&ie=utf-8&oe=utf-8). – Luke Jun 12 '17 at 00:02
  • 3
    Btw, there is a third way: `void f(int array[N])`, which is no different from those two. – HolyBlackCat Jun 12 '17 at 00:02
  • 1
    Related: https://stackoverflow.com/questions/22677415/why-do-c-and-c-compilers-allow-array-lengths-in-function-signatures-when-they/ – M.M Jun 12 '17 at 00:03
  • @HolyBlackCat, okay, in what way is that different to the other 2? – Luke Jun 12 '17 at 00:03
  • 1
    As I said, there is no difference. – HolyBlackCat Jun 12 '17 at 00:04
  • @HolyBlackCat, sorry, I didn't see that part of the comment. Wouldn't specifying a size limit the array in some way? – Luke Jun 12 '17 at 00:05
  • 1
    'int array = {0, 1, 2, 3, 4, 5};' this is not a valid array declaration. you can correct it to 'int array[] = {0, 1, 2, 3, 4, 5};' – EsmaeelE Jun 12 '17 at 00:09
  • 1
    @iONinja No. You can write `int array[static 10]` to specify that the source array must be at least 10, but the standard doesn't actually require the compiler to diagnose the problem if a shorter array is passed! So this feature is mostly useless. – M.M Jun 12 '17 at 00:34
  • @EsmaeelE, true. I'll fix that up. – Luke Jun 12 '17 at 01:07
  • @M.M, okay, thanks. – Luke Jun 12 '17 at 01:07
  • @dasblinkenlight, sorry, you're right. The term "passing" is indeed correct. – Luke Jun 12 '17 at 01:09

4 Answers4

14

In your specific example there is no difference.

In more general case one difference between these two approaches stems from the fact that in case of [] syntax the language performs "usual" checks for correctness of array declaration. For example, when the [] syntax is used, the array element type must be complete. There's no such requirement for pointer syntax

struct S;
void foo(struct S *a); // OK
void bar(struct S a[]); // ERROR

A specific side-effect of this rule is that you cannot declare void * parameters as void [] parameters.

And if you specify array size, it has to be positive (even though it is ignored afterwards).

radrow
  • 6,419
  • 4
  • 26
  • 53
AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
3

There is no difference apart from the syntax. For historical reasons, even though int array[] looks like it should pass an array, it actually passes a pointer (meaning it's the same as int *array).

If I were you, I would prefer int *array just because it does what it looks like it does - that is, it's less likely to confuse you.

user253751
  • 57,427
  • 7
  • 48
  • 90
  • 2
    I find it scary that, in this day and age, advice like this is given. – user3344003 Jun 12 '17 at 00:33
  • 3
    @user3344003 You have two options - one that looks like it declares a pointer, and declares a pointer, and one that looks like it declares an array, and declares a pointer. What is your reasoning for ever using the second one? – user253751 Jun 12 '17 at 00:37
  • 1
    @immibis Some people consider that the array declarator documents intent that the pointer should be a pointer to an element of an array . (There are problems with this of course...) – M.M Jun 12 '17 at 00:54
  • 1
    @M.M Not to worry...it is. *a is a pointer to a[0] :) And I 110% agree with immibus that *array is the better syntax (although maybe not because it's "less confusing", but rather simply because its syntax more unambiguously suggests its semantics). – John Forkosh Jun 12 '17 at 04:56
  • @JohnForkosh That's what I meant by "less confusing"... Especially for people who are new to C and haven't learned all its quirks yet. – user253751 Jun 12 '17 at 05:05
  • I find it quite confusing that just the name (in this case `array` WITHOUT the brackets) is not used as the pointer in a function prototype and header but then inside a function is. So, in a function prototype and header, `array[]` and `*array` are pointers to the storage place of `array[]`. Whereas INSIDE `main()` and `function()` the array pointer that is passed to `function()` is `array` and `*array` and the declaration of the array is, `array[]`. What's not confusing about that?!?!? – Dan Dec 27 '18 at 18:30
  • @Dan that is why I said it was less confusing to use `*array` in the function prototype which makes it obviously a pointer. – user253751 Dec 28 '18 at 04:26
1

They are identical, by definition. The calling code always passes an array argument as a pointer, even if it looks like the caller is passing an array. The array-like parameter declaration might make it look more like the call, but the pointer parameter declaration more accurately reflects what's actually going on.

See also this entry in the C FAQ list.

As Dennis Ritchie explains in "The Development of the C Language", the pointer declaration is actually a "living fossil", a relic from a very early version of C where arrays and pointers worked quite differently.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
1

They are the same when passing an array into a function, however, they are NOT the same in general. Consider the following code snippet:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *mod_string(char *str) {
  puts(str);
  str[0] = 'h';
  puts(str);
  return str;
}

int main() {
  char hello_world[] = "Hello world";
  mod_string(hello_world);
}

If you run this, you will get

Hello world
hello world

However, if you change the first line of the program to

char *hello_world = "Hello world";

When you run the program the output will be

Hello world
Segmentation fault (core dumped)

I'll leave it to the C experts to properly explain this, but I just wanted to point out that the notation differences are NOT syntactic sugar.

Eratosthenes
  • 2,280
  • 1
  • 14
  • 11
  • The two ways of defining the function are in fact exactly identical. You will of course get different behavior if you pass a pointer to read-only memory as opposed to writable memory and attempt to write to that memory, but that doesn't mean the function definitions are different. – dbush Jun 29 '21 at 18:02
  • Call me old-fashioned but my definition of "different" is as follows: If you get different outputs, they're different. – Eratosthenes Jun 29 '21 at 18:06
  • To clarify: you'd get the same results if the function was declared as `char *mod_string(char *str) {` or `char *mod_string(char str[]) {` which is what the question is asking about. – dbush Jun 29 '21 at 18:11
  • Right, I said upfront that they're the same when passing them as parameters. However, simply saying that they are interchangeable is not correct, and can cause serious problems if you treat them that way. – Eratosthenes Jun 29 '21 at 18:14
  • If you pass in different values you'll get a different result, but that's not what the question was about. It's about the usage of `char *` vs `char []` as a parameter to a function, not in general. – dbush Jun 29 '21 at 18:15