One of the rare cases where I think he's just not seeing the whole picture. For one, sizeof is not a runtime function but evaluated at compile time. (pretty obvious). More importantly, sizeof is syntactically a unary operator. It isn't syntactically a function call, just like "-a" or "*a" aren't function calls.
That's just how it is, and really what's wrong with it? We're not in lisp after all. Let's not pretend it's a function, because otherwise an expression like
In a alternative world where WG14 all got hit by a bus in 1988 sizeof could be a runtime function that the compiler could replace with a compile time constant as an optimization. Lets say Richie won and phat pointers were added to the language. Then sizeof(phat_pointer) would absolutely be a run time function.
But it's not. And there is no reason why getting the size out of a fat pointer at runtime would need to be done by the same syntactic construct that otherwise does static calculations.
Duh, C also doesn't have fat pointers. And C doesn't have a runtime_sizeof keyword. How do you get from this to "The existing sizeof should be re-purposed to be evaluated at runtime"?
It is a tool I use all the time. I am not concerned about keeping an unaltered timeless gem (which it isn't), but rather things like clarity, orthogonality, simplicity, minimality of concepts etc.
Honestly I am not even sure I am missing fat pointers, other than getting some better diagnostics in pretty rare cases of out-of-bounds access. For coding, I much prefer separate, explicit length fields. I can have as many of them as I need and mutate them as I need. Much more flexible.
The hidden size field of a fat pointer would be more appropriate for a "capacity" field (think std::vector capacity() vs size()) since that is indeed -- more or less, usually -- immutable after allocation of the buffer.
However that is not the "size" field that most would be interested in, not the size field that defines that range of valid data. So again, would be mostly useful for diagnostics, and only if there is a well defined allocation size.
There are some other concerns I have with fat pointers. Let's consider two fat pointers with the same address but different length, how should they compare, p1 == p2 or p1 != p2? Neither p1 < p2 nor p1 > p2 would be a good choice, they would both probably break a lot of code. There is probably quite a lot of code that deducts p1==p2, however substituting p2 for p1 could lead to breakage due to different lengths.
This seems to me like a strong argument against fat pointers, seeing that problems arise from too much magic. While it could be made to work with the standard (since I guess doing any comparison between p1 and p2 could be UB considering p1 and p2 as pointing to different "objects" / one of them invalid), it's probably a path I would not want to go down.
Another, less theoretic and much more practical concern is this: How do you plan to make fat pointers compatible with existing software? If the normal pointer syntax is taken as-is and repurposed to represent fat pointers, those fat pointers will now be bigger than before. I suppose that a good chunk of existing projects would break, and would require significant porting work.
It is ratholes like this that WG14 seems to have mostly avoided rather successfully, and I value that. If you want more features, there is a different language with another philosophy, so no reason for posting negative sentiments (including subtle aggression like "hit by a bus" etc).
It used to be compile-time only until C99, which allowed it to be applied to a variable-length array (VLA). Thus it potentially has run-time semantics, though still not a function. Address-of (&) has run-time semantics, since the address of an object is rarely constant, and isn't a function either.
When using variable-length arrays (which I know are being phased out but which still do exist in the language) sizeof is indeed evaluated at runtime. It's weird.
This requires no initialization code to run; linking resolves it.
Very long ago I made a GUI help system for a program, where all the documentation nodes were represented as structures with pointers for their navigation links: next section, previous section, up, children ...
I statically declared the entire content with declarations akin to the above circular_list.
The help GUI was just a window which displayed the node contents, and the buttons like next and prev just chased the pointers to another node which would replace the displayed content.
Worked like a charm.
Good luck giving that to internationalization people to translate. Haha!
It's probably silly to start remote-lawyering with Mr Torvalds of all people, but that is obviously false, and (also obviously) he knows it.
If it acts exactly like a function, show me its prototype, and how you would call it through a function pointer. I'll be here, waiting while thumbing through my old K&R, or something ...
Also, when using variable-length arrays (which are being phased out, but they are in for instance C99) this works:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
size_t arglens[argc];
for (size_t i = 0; i < sizeof arglens / sizeof *arglens; ++i) {
arglens[i] = strlen(argv[i]);
}
printf("Computed %zu lens:\n", sizeof arglens / sizeof *arglens);
for (size_t i = 0; i < sizeof arglens / sizeof *arglens; ++i) {
printf("%zu: '%s' is %zu\n", i, argv[i], arglens[i]);
}
return 0;
}
Compile (as C99!) and run:
$ gcc -o arglens -std=c99 arglens.c
$ ./arglens foo bar baz fooofooofoo
Computed 5 lens:
0: './arglens' is 9
1: 'foo' is 3
2: 'bar' is 3
3: 'baz' is 3
4: 'fooofooofoo' is 11
Notice how sizeof is computing the size of a run-time sized array. Very much unlike a function.
Edit: fix indent for code formatting (hard tabs don't work).
I agree with his preference, but I think the reasoning should go like `sizeof` is an operator with possibly unclear operator precedence, while `return` is a statement.
> But "sizeof()" really is a function. It acts exactly like a function of it's argument. There is no reason to not treat it that way.
https://lkml.org/lkml/2012/7/11/103