Array passed as function parameters

E

Eric Sosman

Keith said:
Vincenzo Mercuri said:
Il 16/08/2012 20:10, Varun Tewari ha scritto:
In 1, you actually duplicating the array in the funciton.
in 2, rather you are happy using a reference to the array, hence no duplication.

Wrong, AFAIK the only way to "pass an array by value" is by using a common
"trick": declare an array inside a struc and pass that struct as argument
to a function:
[snip]

Yes, but you can only do that with arrays whose size is known at
compile time (you can't have a VLA as a struct member), which limits
its usefulness.

You could use a flexible array member instead, which would come to much
the same thing. (Or the infamous C89 "struct hack", which as far as I
know was never guaranteed to work, but which does in every C compiler
anyone's tested.)

Neither will work for the purpose of passing an array by value.
Concerning the flexible array member, 6.7.2.1p18 says

In most situations, the flexible array member is ignored.
In particular, the size of the structure is as if the
flexible array member were omitted except that it may have
more trailing padding [...]

In other words, the size of the called function's parameter -- the
"local variable" that stores the caller's argument value -- does
not include the flexible array, so there's no place for the callee
to store that array's value.

Same problem with the struct hack: Only the declared part of
the hacked array (usually of size [1]) is actually part of the
struct. Pass the struct by value, and only that declared part of
the hacked array is part of the value; any extra stuff is not
passed because (as far as the language knows) it's not even there.
 
A

ais523

Eric said:
Neither will work for the purpose of passing an array by value.
Concerning the flexible array member, 6.7.2.1p18 says

Right, I'd forgotten that the compiler wouldn't take the actual size of
the variable into account when passing it by value, just the declared
size. You would indeed need an actual VLA (which unfortunately isn't
allowed inside structs), because it's the only sort of flexible-size
storage where the actual size is taken into account by things like
sizeof.

It's not 100% obvious to me that the standard's wording is correct here,
though. Does the standard anywhere say that passing an object by value
passes a number of bytes equal to the object's size, rather than the
whole object? (It's obvious when you think about typical
implementations, but being obvious doesn't necessarily mean that the
standard says it.)

Compilers definitely use your interpretation, at least. I was
interested, so I tested:

$ cat a.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct t {
int length;
char flexible[];
};

void print_t(struct t x) {
puts(x.flexible);
}

int main(void) {
struct t *tp;
tp = malloc(sizeof (struct t) + strlen("Hello, world!") + 1);
tp->length = 13;
strcpy(tp->flexible, "Hello, world!");
print_t(*tp);
return 0;
}
$ gcc --std=c99 -Wall -Wextra a.c
$ ./a.out
(binary garbage)

I'm pretty sure the resulting binary garbage can only possibly be a
symptom of undefined behaviour; an interesting implementation quality
issue that gcc didn't give any diagnostics on the program. (Warning
about passing structs with flexible members by value would seem like a
reasonable warning.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
474,078
Messages
2,570,570
Members
47,204
Latest member
MalorieSte

Latest Threads

Top