News for hackers. Stuff that matters.
Re:Linus on compiler warnings and code reviews by acconsta on Wednesday September 23, 2015 @03:37PM (#10267566)
Does anyone know why array arguments decay to pointers?
Re:Linus on compiler warnings and code reviews by syncsynchalt on Wednesday September 23, 2015 @03:47PM (#10267651)
Because that's how the machine sees C arrays. It would take an extra (invisible) parameter on the stack to implicitly pass the array size into the function, a thing which is very much against the spirit of C.

The only real surprises/magic in C are things like:

  - addition/subtraction on typed pointers has an implicit multiply by sizeof(type)
  - type conversion between floats and ints
Re:Linus on compiler warnings and code reviews by maximilianburke on Wednesday September 23, 2015 @04:06PM (#10267767)
> Because that's how the machine sees C arrays. It would take an extra (invisible) parameter on the stack to implicitly pass the array size into the function, a thing which is very much against the spirit of C.

It would only require a separate parameter if you needed to pass arbitrary-sized arrays. In this example, if the prototype contains the array size:

    int foo(char array[30]);
It would not be difficult for the compiler to only allow arrays of that length to be passed as parameters, and no invisible parameters are necessary, assuming also that the function implementation made the same assumption of array length.

Developers who handle arrays of arbitrary length tend to already encode a length parameter, it's this case where it looks to the developer like they are encoding a length value that is the deceptive/problematic case.

Re:Linus on compiler warnings and code reviews by mortehu on Wednesday September 23, 2015 @04:26PM (#10267905)
This is one of the many uses of the static keyword in C99:

  void ten(char foo[static 10]) { }

  void generates_warning() {
    char foo[3];
    ten(foo);
  }
This causes clang to emit the following warning:

> warning: array argument is too small; contains 3 elements, callee requires at least 10

Re:Linus on compiler warnings and code reviews by merlincorey on Wednesday September 23, 2015 @04:43PM (#10268038)
The warning is true - it is "at least" 10:

    char ten(char foo[static 10]);

    char ten(char foo[static 10]) { return foo[1]; }

    void generates_no_warning(void);

    void generates_no_warning() {
        char foo[30];
        ten(foo);
    }

    int main() {
        generates_no_warning();
    }
Modified also so it would build cleanly with -Weverything -Werror
Re:Linus on compiler warnings and code reviews by uxcn on Wednesday September 23, 2015 @05:15PM (#10268287)
It avoids stepping on memory elsewhere in the program though. My personal preference for C99 and above is to pass the length as a parameter.

    int do_stuff(size_t len, int64_t arr[len]);
It still suffers from the pointer decay problem, but it at least forces whoever is reading/writing the code to acknowledge the length.
Re:Linus on compiler warnings and code reviews by uxcn on Wednesday September 23, 2015 @05:27PM (#10268363)
How does that parse? I thought static was only a storage class.
Re:Linus on compiler warnings and code reviews by syncsynchalt on Wednesday September 23, 2015 @05:51PM (#10268504)
When extending the language, the committee will often try to re-use existing reserved keywords to avoid colliding with a variable name in someone's code.

Thus we have yet another overloading of "static" in C, the use of "auto" in C++11 (which worked out quite well), and interesting type names such as "long long" in both.

When the committee breaks this rule (think nullptr in C++11) they first must choose a name which is suitably rare (and often a bit clunky as a result), they then scan for that name in large code corpuses, and evaluate how much work they are making for the maintainers of any codebase that's going to be compiled against a new compiler (and which may need to be modified to do so).

Some languages (I'm thinking JS specifically) have keywords that are not in use but are still reserved in case they may be useful in the future.

Re:Linus on compiler warnings and code reviews by geocar on Wednesday September 23, 2015 @04:15PM (#10267838)
> It would not be difficult for the compiler to only allow arrays of that length to be passed as parameters

It would be extremely difficult for the compiler, without changes to the C spec and most ABIs, to simultaneously provide that protection for heap-allocated objects, for example:

    foo(malloc(30));

> Developers who handle arrays of arbitrary length tend to already encode a length parameter, it's this case where it looks to the developer like they are encoding a length value that is the deceptive/problematic case.

The most common arrays of arbitrary length in C programs are almost certainly C "strings" which are usually 0-terminated instead of including a length value.

Re:Linus on compiler warnings and code reviews by Athas on Wednesday September 23, 2015 @04:06PM (#10267771)
> Because that's how the machine sees C arrays. It would take an extra (invisible) parameter on the stack to implicitly pass the array size into the function, a thing which is very much against the spirit of C.

In this case, the size is specified as a compile-time constant, however, which seems like it could work. All it would do is change the semantics of sizeof(), really.

Also, I am doubtful whether it would really be a problem to have "invisible" parameters. C doesn't even specify a stack as I remember it, and compilers are certainly free to pass as many function parameters in registers as they are able to.

Re:Linus on compiler warnings and code reviews by syncsynchalt on Thursday September 24, 2015 @01:28PM (#10273065)
True, someone else pointed out that this could all be done as compile time checks, which would have no runtime/ABI impact.

There are interesting stories from the early days of C when it was first codified that say a lot about the whys and hows of the language that we have today. In particular I'm thinking of the fact that the compiler and what we now think of "compiler warnings" came from two different warnings (cc vs lint). This is because the C compiler was the largest C program and generally took every bit of memory available to do it, there was no room for any kind of sanity checking on that code. I've heard it said that to include a new feature "n" in the language, they generally had to rework at least some of the existing compiler code with feature "n-1" to simplify/shrink it enough to fit the new feature.

In that kind of environment you get a language with very little input checking, beyond the rules of the grammar itself (which was as small as possible).

Re:Linus on compiler warnings and code reviews by geocar on Wednesday September 23, 2015 @04:19PM (#10267864)
It is an ABI change.
Re:Linus on compiler warnings and code reviews by acconsta on Wednesday September 23, 2015 @04:02PM (#10267747)
But the size of C89 arrays is fixed and known at compile time. Why would the length need to be passed?
Re:Linus on compiler warnings and code reviews by klodolph on Wednesday September 23, 2015 @04:51PM (#10268094)
It's not necessarily known by the caller, since the array might be declared with an unspecified size and defined in a different translation unit.
Re:Linus on compiler warnings and code reviews by acconsta on Wednesday September 23, 2015 @05:54PM (#10268518)
"might" is the key word there though. What if the array has a statically known size, like the code sample in the email?

I suppose it could just be for consistency.

Re:Linus on compiler warnings and code reviews by GuamPirate on Wednesday September 23, 2015 @03:46PM (#10267638)
Well, the information isn't copied... so if you modified the incoming array you modify the original, so in that sense it has to be a pointer. Arrays and pointers are analogous in C except when they are declared, as there is an implicit allocation of information. Since we don't want this when it comes to array arguments, it simply decays.
Re:Linus on compiler warnings and code reviews by doppelganger27 on Wednesday September 23, 2015 @03:45PM (#10267626)
In C (and in all other languages I can think of), an array is actually a pointer to a bunch of memory. Indexing into the array calculates offset from the array pointer, and grabs the item at that offset.
Re:Linus on compiler warnings and code reviews by 36erhefg on Wednesday September 23, 2015 @04:40PM (#10268008)
Array is not a pointer. Your description of indexing is not correct, neither is the phrase "array pointer" you invented. The machine code produced will calculate the offset differently for a pointer and an array.
Re:Linus on compiler warnings and code reviews by doppelganger27 on Wednesday September 23, 2015 @04:51PM (#10268098)
Let me clarify with an example. Suppose you have an array:

  int a[10]
There is a section of memory of size sizeof(int) * 10 somewhere, and the variable a is a * int that points to that section. When someone does this:

  int x = a[2]
It is equivalent to:

  int x = *(a+(sizeof(int)*2))
When I said "array pointer" in my previous comment, all it meant was the memory address that the variable (which is an array) points to (in the example, the variable "a")

Edit: missing paren

Re:Linus on compiler warnings and code reviews by 36erhefg on Wednesday September 23, 2015 @04:58PM (#10268156)
a is a label, or an alias of a memory address. It is not a pointer. ( Your third example has a mistake, the correct increment is: a+2, because pointer arithmetic increments in object size not byte size )

Read this:http://eli.thegreenplace.net/2009/10/21/are-pointers-and-arr...

Re:Linus on compiler warnings and code reviews by doppelganger27 on Wednesday September 23, 2015 @05:03PM (#10268218)
Interesting read. Thanks :)
Re:Linus on compiler warnings and code reviews by nickcw on Wednesday September 23, 2015 @03:52PM (#10267679)
FYI the equivalent Go code would actually copy the whole array on the stack, and so it would be valid if possibly inefficient depending on the size of the array.
Re:Linus on compiler warnings and code reviews by ashearer on Wednesday September 23, 2015 @04:08PM (#10267783)
...and for anything larger than a small fixed-size array (like the example), you'd avoid data-copying overhead by passing a slice, which is a bounds-checked bundle of pointer and length.
Re:Linus on compiler warnings and code reviews by esaym on Wednesday September 23, 2015 @04:25PM (#10267898)
Because as Linus stated: "array arguments in C don't actually exist"

The bracket notation ex: myarray[2] is actually just a sugar syntax for: * (myarray+2)

An array is nothing more than an address and a (hopefully) know length. Not really a "data structure" or object by no means.

You could definitely roll your own though with something like:

  struct  {
    char * arr,
    int size
  } my_struct;
  
  for(int i = 0; i < my_struct.size; i++){
    printf('%x', my_struct.arr[i]);
  }

  ect,
Re:Linus on compiler warnings and code reviews by acconsta on Wednesday September 23, 2015 @04:29PM (#10267932)
Yeah. But why is that the behavior specified by the standard?
Re:Linus on compiler warnings and code reviews by pjmlp on Wednesday September 23, 2015 @04:15PM (#10267833)
Because C designers decided to ignore other saner systems programming languages and thought it was a cool idea to do that.

No, C wasn't the first systems programming language used to write OSes.

Re:Linus on compiler warnings and code reviews by augustk on Wednesday September 23, 2015 @03:47PM (#10267654)
Because the compiler gets the length of an array from its declaration. However, inside a function the compiler cannot tell the size of the actual array parameter.
Re:Linus on compiler warnings and code reviews by acconsta on Wednesday September 23, 2015 @04:04PM (#10267753)
If I write:

void example(int a[10]);

Why can't the compiler tell a is an int array of size 10 instead of a pointer?

Re:Linus on compiler warnings and code reviews by 36erhefg on Wednesday September 23, 2015 @04:43PM (#10268037)
Because a is a pointer and not an array. That is by design.

When you pass an array to this function you are not copying the entire array, C is pass by value, therefore you must pass a pointer. In fact a behaving like an array would be lying to the programmer since you didn't make a copy of the array.

Re:Linus on compiler warnings and code reviews by acconsta on Wednesday September 23, 2015 @08:22PM (#10269161)
You can pass structs by value. Why not arrays?
Re:Linus on compiler warnings and code reviews by 36erhefg on Wednesday September 23, 2015 @08:44PM (#10269224)
Your answer is merely a simple online search away.
Re:Linus on compiler warnings and code reviews by acconsta on Wednesday September 23, 2015 @09:09PM (#10269283)
What's weird is five hours after asking that question, no one has provided a reasonable explanation of why C requires arrays to become pointers on function boundaries.

My "online search" found Walter Bright, who knows a thing or two about C compilers, wondering the same thing:

https://news.ycombinator.com/item?id=7572011

Re:Linus on compiler warnings and code reviews by 36erhefg on Wednesday September 23, 2015 @11:36PM (#10269698)
Improve your searching capabilities.

https://programmers.stackexchange.com/questions/245602/why-c...

( https://stackoverflow.com/questions/7454990/why-cant-we-pass... )

And partially this thread.

As for Walter; Stop using C like you want it to be used, and instead how it is meant to be used. The article takes a strawman position. Anyone who takes their time and learns C, knows that arrays decay.

Re:Linus on compiler warnings and code reviews by acconsta on Thursday September 24, 2015 @09:05PM (#10275889)
So it comes down to historical compatibility with B? Wow.
Re:Linus on compiler warnings and code reviews by doppelganger27 on Wednesday September 23, 2015 @04:34PM (#10267980)
There is no strict difference between a pointer and an array (of any size) at run time in C. Arrays are just pointers to a section of memory, and it's up to the programmer to communicate how big that section is.
Re:Linus on compiler warnings and code reviews by 36erhefg on Wednesday September 23, 2015 @04:46PM (#10268060)
There are whole separate chapters describing arrays and pointers in the C Standard. This is by definition a strict difference. You should read those chapters and please stop spreading this beginners misconception of C.
[deleted]
Re:Linus on compiler warnings and code reviews by 36erhefg on Wednesday September 23, 2015 @05:02PM (#10268196)
In any case, there are significant differences at runtime as well. Look at the link I posted at your other comment.
Re:Linus on compiler warnings and code reviews by geocar on Wednesday September 23, 2015 @04:10PM (#10267806)
sizeof(a) is sizeof(int*) in your example because of the C standard: That is to say this is a bug in the standard, and not a bug in any particular compiler.
Re:Linus on compiler warnings and code reviews by acconsta on Wednesday September 23, 2015 @04:32PM (#10267957)
Yes, but why does the standard have that bug?
Re:Linus on compiler warnings and code reviews by geocar on Wednesday September 23, 2015 @04:56PM (#10268146)
Probably because the compilers that were standardized had that bug.