static arrays in C functions

Steven Schveighoffer schveiguy at
Tue Dec 8 09:36:28 PST 2009

On Tue, 08 Dec 2009 11:53:12 -0500, Bill Baxter <wbaxter at> wrote:

> On Tue, Dec 8, 2009 at 2:08 AM, Lutger <lutger.blijdestijn at>  
> wrote:
>> Since a while some extern(C) functions which take arrays seem to be  
>> broken.
>> Can anybody clarify /confirm how they should be declared?
>> For example I stumbled upon this:
>> import core.sys.posix.unistd, std.stdio;
>> void main()
>> {
>>    int[2] fd;
>>    writeln( pipe(fd) ); // failes with errno == EFAULT
>> }
>> In core.sys.posix.unistd, pipe is declared as: int pipe(int[2]);
>> This works though:
>> extern (C) { int pipe(int*); }
>> void main()
>> {
>>    int[2] fd;
>>    writeln( pipe(fd.ptr) );
>> }
> (Assuming you're talking about D2 here...)
> A few releases ago fixed-size arrays changed to be pass-by-value.
> But I guess there's still some logic in there to interpret int[2] as
> int* when inside an extern(C) block.

No it compiles *because* that logic is not there.  It now thinks int[2] is  
a pass-by-value entity.  It links because you are using C linkage which  
does not do name-mangling.  I could define pipe as:

extern (C) int pipe(char c, int x, float y);

and it will still link :)

> It does seem like there's a bug there, though.  I think pipe(fd) in
> the first case should fail to compile because it's attempting to pass
> by value where a pointer is expected.

The error is either:

a) you now need to declare C functions that were declared in C taking an  
array to taking a pointer, so core.sys.posix.unistd (and likely others)  
needs to be fixed.
b) as you suggested, inside a C block, int[2] should be interpreted as int  

I'd prefer a, because I don't care much about direct translation of C  
headers :)  If b is chosen as a solution, I'd also like to have the  
compiler automatically pass the pointer when calling a C function.


More information about the Digitalmars-d-learn mailing list