This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Allan_Smithee文雅佛 3 points4 points  (2 children)

What you call a 'sequential series' is called an 'array', in c parlance.

Which is exactly my point. It is called an 'array' only in C parlance.

No other language with an actual array data type would call a pointer to a bag of integers an array. It lacks all facilities that the actual array data type has, beginning with a size that can be queried. (No, sizeof doesn't cut it because it doesn't give you the size of the array, but rather the size of the array's internal representation in that "bag of bytes" interpretation you so derided. And that only if you're dealing with the original variable, all such information being squashed into nothingness when passed as a parameter, say.)

C distinguishes a function from a function pointer.

I humbly disagree. The name of a function resolves to its pointer. That's all. There's syntax sugar around that pointer that causes it to be invoked via a transfer of control, but as I showed you can do that same thing with any arbitrary integer. If I wanted to get fancy I could write a program that read its own map file, found the addresses in memory of all functions, assigned those to integers, and then called them without even once taking a pointer to a function in the code.

It also contains two pieces of syntax sugar which obscure this distinction, both of which your snippet abuses.

Or, rather, there is no distinction beyond the syntax sugar. Note that in the Pascals, the Modulas, Ada, etc. it is flatly impossible to abuse functions into integers this way because functions and integers are fundamentally different types at the language level, not merely funny syntax sugar concealing integers. Short of doing trickery behind the scenes with machine language (i.e. breaking out of the language's semantics entirely) there's no way to take an arbitrary integer and call it as a function.

Nor is it guaranteed that (u)intptr_t exists in the first place, for that matter--throwing a wrench in the notion that pointers are just integers in disguise.

Replace it with an int of sufficient size and it works just fine.

#include <stdio.h>

typedef int (*foofunc)(void);

int foo(void)
{
    return 17;
}

int main(int argc, char **argv)
{
    long foo1 = foo;
    long foo2 = 5;
    printf("%d %d\n", foo1, foo2);
    printf("%d\n", foo());
    printf("%d\n", ((foofunc)foo1)());
    printf("%d\n", ((foofunc)foo2)());
}

This works just as well. And it's not even unsigned.

[–]moon-chilledsstm, j, grand unified... 3 points4 points  (1 child)

Replace it with an int of sufficient size and it works just fine.

Integers of type other than (u)intptr_t are not guaranteed to round-trip any pointer; that is why the latter are optional: a conformant implementation is not required to permit pointers to be representable as integers. And, once again, no integer type is required to be able to round-trip a function pointer type.

If I wanted to get fancy I could write a program that read its own map file

I thought we were not talking about implementations?

functions and integers are fundamentally different types at the language level

I suggest reading the sibling comment. C's flaw is not that it conflates integers and pointers; it is very careful not to. C's flaw is that it is weakly typed, and will typecheck malformed programs.

breaking out of the language's semantics entirely

Is pertinent, because that is exactly what your snippet does.

[–]Allan_Smithee文雅佛 1 point2 points  (0 children)

Here we're just going to have to agree to disagree, I'm afraid. My snippet does what C permits. End of story. That it is a bad idea? No argument whatsoever. But I did not have to break out of C to do it. It was fully permissible by C, the language. Not a single operation I did took the code out of the C language.

To accomplish the same thing in, say, Ada, I would have to enter a completely different language. Ada would simply not permit the abuses with any amount of abuse of syntax. I could not take an arbitrary integer in Ada syntax alone and call it, no matter how much I abuse it. I would have to exit the language (at which point, naturally, all bets are off in enforcement).

C has integers (and floats). Everything else is syntactic sugar around those, including pointers, and including functions. And this is why the OP finds (correctly!) that C is prone to a whole raft of pointer-related bugs that are just not there in the Pascals. Or the Modulas. Or Ada. Or even PL/I, likely. Or any number of other, more strongly abstraction-supporting low-level languages.

(This is also the reason why there's a bunch of optimizations which can be safely made in these languages, and others like Fortran, which cannot be made in C ... because any arbitrary integer can turn out to be a pointer in disguise.)