11
  • foo(char *s)
  • foo(char *s[ ])
  • foo(char s[ ])

What is the difference in all these ?

Is there any way in which I will be able to modify the elements of the array which is passed as argument, just as we pass int or float using & and value of actual arguments gets modified?

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
mightyWOZ
  • 7,946
  • 3
  • 29
  • 46
  • 1
    Hard for me to understand what you mean, but second option is wrong. It's pointer to an array, so in fact pointer to pointer, not a pointer to a value. first and second - there is no difference between them. I would use first one to indicate, that I am passing pointer to a char and second to indicate, that I am passing array of chars (pointer to a first char in table.). Second part of qestion I simply do not understand. You can modify elements in all of these methods. – DawidPi Sep 03 '15 at 13:46
  • 3
    My friend `char *s[]` is not a char array . – ameyCU Sep 03 '15 at 13:47
  • `char (*s)[]` would be a pointer to a char array. `char *s[]` is an array of char pointers. – zneak Sep 03 '15 at 13:48
  • Thanks @DawidPi i am new to c and didn't know the difference between all these , thats why i may have listed one wrong option – mightyWOZ Sep 03 '15 at 14:15
  • @Balraj Please do not edit the question and __add__ additional questions, once the initial question is answered. You can use the comment section under an answer or ask a new question, if you need more info. Thanks. – Sourav Ghosh Sep 03 '15 at 14:44
  • Sorry . point noted. – mightyWOZ Sep 03 '15 at 14:53

4 Answers4

12

It is not possible in C to pass an array by value. Each working solution that you listed (which unfortunately excludes #2) will not only let you, but force you to modify the original array.

Because of argument decay, foo(char* s) and foo(char s[]) are exactly equivalent to one another. In both cases, you pass the array with its name:

char array[4];
foo(array); // regardless of whether foo accepts a char* or a char[]

The array, in both cases, is converted into a pointer to its first element.

The pointer-to-array solution is less common. It needs to be prototyped this way (notice the parentheses around *s):

void foo(char (*s)[]);

Without the parentheses, you're asking for an array of char pointers.

In this case, to invoke the function, you need to pass the address of the array:

foo(&array);

You also need to dereference the pointer from foo each time you want to access an array element:

void foo(char (*s)[])
{
    char c = (*s)[3];
}

Just like that, it's not especially convenient. However, it is the only form that allows you to specify an array length, which you may find useful. It's one of my personal favourites.

void foo(char (*s)[4]);

The compiler will then warn you if the array you try to pass does not have exactly 4 characters. Additionally, sizeof still works as expected. (The obvious downside is that the array must have the exact number of elements.)

zneak
  • 134,922
  • 42
  • 253
  • 328
  • It is actually possible to pass arrays by value. And please note that the compiler is actually not forced to warn you about incompatible pointer types when you show the wrong pointer type into an array pointer, though good compilers do. An alternative to better type safety might be the VLA syntax: `void foo (size_t n, char s[n])`. This still gets boiled down to a pointer to the first element, because C makes no distinction between "parameter decay" of regular arrays and VLAs – Lundin Sep 03 '15 at 14:42
  • 1
    @Lundin, you'd be teaching me something today if you showed me how to pass an array by value (and not a structure wrapping an array, mind you). – zneak Sep 03 '15 at 14:45
  • @Lundin Ah, the old "actually possible to pass arrays by value" but code is really "passing a structure by value" trick. Maxwell Smart would be proud. – chux - Reinstate Monica Sep 03 '15 at 15:46
  • @chux As far as the machine code (aka the real world outside the C standard) is concerned, your program is passing an array by value. – Lundin Sep 04 '15 at 06:12
4

Scenario: You're calling the function with an array as argument.

In that case,

 foo(char *s)

and

 foo(char s[])

are considered equivalent. They both expect to be called with a char array.

OTOH, foo(char *s[ ]), is different, as it takes the address of a char * array.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
4
  • foo(char *s) is pretty straight-forward, it is just a pointer, which could potentially be a pointer to the first element of an array.

  • foo(char s[]) is a declaration of an array of char, but because of a (stupid) rule in the C standard, this gets translated to a pointer to char. Similarly, if you declare any array size, you still get a pointer to char.

    Mentioned rule can be found in C11 6.7.6.3 Function declarators:

    A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’

    It would perhaps have been much better if this strange, confusing "would-be-array" syntax was banned entirely, as it is 100% superfluous and fills no other purpose but to confuse beginners who try to join the "C club". But then C was never a rational language...

    Some will say that the the rationale is that you should never be allowed to pass arrays by value in C, for performance reasons. Well, tough luck, because you still can, despite this rule.

  • You can "hack the C standard" and pass an array by value:

    typedef struct
    {
      char array[10];
    } by_val_t;
    
    foo (by_val_t arr);  // bad practice but possible
    

    Now there's really never a reason why you would want to pass an array by value, this is very bad program design and doesn't make any sense. I merely included this example here to prove that the rule in 6.7.6.3 completely lacks any rationale.

  • You could pass an array pointer as a parameter to a function. This is where things turn advanced, as this is quite obscure and has very limited practical use:

    foo(char(*s)[])
    

    If you specify an array size here, you actually get a bit of added type safety because compilers tend to warn about casts between array pointers of different size.

    But note that array pointers are mainly just there to make the C language more consistent. There's very few reasons why you would ever want to pass an array pointer to a function (here is one somewhat complex example where I apparently found a valid use for it).

Community
  • 1
  • 1
Lundin
  • 195,001
  • 40
  • 254
  • 396
0

foo(char *s), foo(char *s[ ]), foo(char s[ ]) , what is the difference in all these ?

In these foo(char *s) and foo(char s[ ]) both will expect char array as argument.

Exception remaining this -foo(char *s[ ]) this will expect a array of pointers to chars as argument.

ameyCU
  • 16,489
  • 2
  • 26
  • 41