Once the point is home, you can drive it a little bit more by exploiting the fact that string literals can be converted to pointers to the first characters, and do
A reference is functionally equivalent to a const pointer. (Reference reassignment is disallowed. Likewise, you cannot reassign a const pointer. A const pointer is meant to keep its pointee [address].)
The difference between them is that C++ const references also allow non-lvalue arguments (temporaries).
It is much easier to read from right to left when decoding types. Look for yourself:
- double (* const convert_to_deg)(double const x) // const pointer to function taking a const double and returning double
- int const (* ptr_to_arr)[42]; // pointer to array of 42 const ints
- int const * arr_of_ptrs[42]; // array of 42 pointers to const ints
If array were, say, uint32_t* then what `*(array + i)` would do is actually `(intptr_t)array + i * 4` and not `(intptr_t)array + i`. If array were uint16_t* then it's `(intptr_t)array + i * 2`. In short the way the pointer arithmetic gets translated greatly depends on the type of the pointee and thus is not as primitive as it can be.
I think it depends on the coder if it makes more sense to them to write out the scale by element size or not. For me, the `+` is just pointer arithmetic and of course an addition in number of elements (so I don't think of the scaling at all).
Just saying that "actually it's just array + i" makes more sense - for me(!).
They exist in the sense that their length is sometimes known if the full definition is visible. sizeof(array) isn't the same as sizeof(generic ptr to array).
This is not entirely a complete view. For example, sizeof() operator returns the declared size of an array. It seems that C recognizes the concept of an array.
> nobody really does that, because that would be kind of insane
Yeah. That's why people don't do things in C. It's more like most C programmers probably weren't aware of this. After your comment, we'll start to see C codebases everywhere with that.
Most programmers probably weren't aware of this, but no true Scottish C programmer would be unaware of it.
If you want to manipulate memory directly - which is risky though sometimes useful - C is one of the best languages in which to do it. Memory addresses are numbers, and C will let you work with those numbers in whatever way you want: add, subtract, multiply, divide... and if you didn't shudder at the suggestion of dividing a pointer because there are very, very few reasons to do so then C is not the language for you!
If you don't want to manipulate memory directly, you probably shouldn't be using C; stick with a nice garbage-collected, type-safe, object-oriented, cross-platform language. If you do want to manipulate memory directly, but you want more guarantees on what you can do with pointers, try Rust.
Just wanted to clarify that Rust allows for the same manipulation as C, it just all has to happen in the context of an unsafe code block. I think your comment might be taken to imply that Rust isn’t as capable as C in that regard.
On some ancient systems { and } don't exist. So an alternarive made of more common characters is provided. There is also a two-character combination for [ and ] and a three character combination for |, & and some other characters. The feature is called digraphs/trigraphs and is disabled on most modern compilers by default.
> The feature is called digraphs/trigraphs and is disabled on most modern compilers by default.
Digraphs and trigraphs are treated differently. <% and %> are fine on GGC and Clang, but ??< and ??> are disabled by default. Both need the -trigraphs option.
It's actually spelled out in K&R in more technical language:
"The array subscripting operation is defined so that E1[E2] is identical to *(E1+E2). Therefore, despite its asymmetrical appearance, subscripting is a commutative operation."
int i;
int main(){
for(
;
i["]<i;++i){--i;}"]; // loop until i == 14? (the NUL byte on the end)
read('-'-'-',i+++"hello, world!\n",'/'/'/') // read(0, <one byte of "hello, world!\n" at a time>, 1)
) {};
}
int read(j,i,p){
write(j/p+p,i---j,i/i); // write(0/1+1, i-- - 0, 1) --> write(1, i, 1) --> write a byte to STDOUT
}
To really drive home the primitiveness of C arrays, should probably also mention that, because addition is commutative, you could also write
and somewhat surprisingly, it will compile, and work, and it means "*(i + array)" which is equivalent to "*(array + i)"But nobody really does that, because that would be kind of insane.