Ptr+1 != int+1

show me where pointer arithmetics are necessary

Other urls found in this thread:

en.wikipedia.org/wiki/Commutative_property
twitter.com/NSFWRedditVideo

Arrays.

indexing

Like all data structures

>ptr+1 != int+1
Are there actually people who have at least one month of programming experience and believe that ptr+1 equals int+1?

EVERY-fucking-WHERE!!!1!

Array indexes is essentially pointer arithmetic.

In C this is valid array notation:
int array[3] = {1, 2, 3};

int index = 0;
index[array] = 1;

>In C this is valid array notation:
It's not valid C but it will likely work if compiler doesn't give error.

I was more asking why/when it is necessary for the language to expose them. Sure they are used in assembly and thus in language internals.

wherever you want to modify data outside of scope

>It's not valid C
How is it not valid C?

>I was more asking why/when it is necessary for the language to expose them
Because they are more general than for array types.

Imagine implementing memcpy for example without pointer arithmetic.

This will most likely not work as
a[b] = 1; //Equal to:
*(a + b) = 1;
//You are implying this:

array[index] = 1;

//is equal to

index[array] = 1;

//which is not true, as the latter is equal to

*(index + array) = 1; //*(0 + &array) = 1

>array + index is not equal to index + array
But it is.

en.wikipedia.org/wiki/Commutative_property

reversing a string for example

nevermind it is equal, you are correct.
your compiler will still most likely throw a warning
there is also no reason not to conform to conventions

>your compiler will still most likely throw a warning
Why would it? It's perfectly valid notation.

I said warning, not error.
I *will* compile the source code, but it will warn you, because you are specifying an offset to an int and using it as a memory address. It will warn you as you might have typed it by accident (type mismatch).

>I was more asking why/when it is necessary for the language to expose them.

With that attitude you might as well use a different language.

Writing a kernel without the use of pointers won't work out for you.

>I said warning, not error.
Again, why would it throw a warning for *valid* code?

The compiler will only warn about potentially unintended code.

>but it will warn you
It doesn't and it shouldn't.

>because you are specifying an offset to an int and using it as a memory address
No, I am adding a memory reference (array) with an offset (index). As addition is commutative, the ordering of the operands is irrelevant.

>It will warn you as you might have typed it by accident (type mismatch).
It will not though. Neither GCC nor clang throws any warnings, as it is perfectly valid C code.

could you point specific issues where you can't use indexing?

Anything involving a void* pointer.

>The compiler will only warn about potentially unintended code.
which is exactly what's happening here

It's not unintended. Addition is commutative.

You are also demonstratively wrong, seeing how neither gcc nor clang (the objectively two most used compiler suites besides msvc) doesn't throw a warning, even if you enable -pedantic.

>argues against programmer intention by citing the standard
hurr

>a + b is equal to b + a
>"but you should only write a + b because that is what you really intended, you clearly didn't intend to write b + a"
?

kek, I agree with him

> By definition, the subscript operator E1[E2] is exactly identical to *((E1)+(E2)).
It's straight from the standard.

>Again, why would it throw a warning for *valid* code?
Dude, the compiler only throws warnings for valid code. For invalid code it throws errors.

Read the rest of the post before replying, it saves me the trouble of having to quote the very next sentence.

>Java,Javascript and GO
I'm guessing they learn eventually right ?

Actually it is not type-safe
uint8_t a[3] = {1, 2, 3]};
uint16_t b = 0;

a[b] = 0; // *(a + 0 * 1)
b[a] = 0; // *(0 + a * 2)

>Actually it is not type-safe
Actually, it is.

>a[b] = 0; // *(a + 0 * 1)
>b[a] = 0; // *(0 + a * 2)
Wrong.

In both cases they evaluate as
a[b] = 0; // *( + 0) = 0;
b[a] = 0; // *(0 + ) = 0;

You can't do arithmetic on a void pointer.

You can cast it to a pointer you can do arithmetic on.

You can not cast an array.

you forgot to take the width of the actual data into account. this is true for 1-byte big numbers. the offset will always be multiplied by the number of bytes per entry, as every element resides after one another in memory.

>you forgot to take the width of the actual data into account.
The width does not matter, dipshit.

uint8_t a = 1;
uint64_t b = 2;
uint64_t c = a + b; // the result is still 1 + 2, not 1*1 + 2*4


What the fuck are you even implying, retard?

#include
#include

int main()
{
size_t i;
uint8_t array[3] = {1, 2, 3};
uint16_t index = 0;

array[index] = 0;
index[array] = 0;

for (i = 0; i < 3; ++i)
{
fprintf(stdout, "%d ", array[i]);
}
fprintf(stdout, "\n");

return 0;
}


This prints out 0 2 3
Not 0 0 3, as you claim.

in this case the compiler *knows* which one is the array and performs, as you should otherwise run into trouble:
a[b] // *(a + sizeof(*a) * b)
b[a] // *(b + sizeof(*b) * a)

that's not how it works
it's not like the order changes the type of the operands
imagine the implicit types were shown as casts
*(((uint8_t*)a) + ((uint16_t)b))
*(((uint16_t)b) + ((uint8_t*)a))

the type of a is still the same, the semantics of pointer arithmetic don't change no matter what order you do it in
you are still adding b to a value of the pointer type that a was declared as

>in this case the compiler *knows* which one
It always knows, because it uses the width of the pointer type.

#include
#include

void youre_still_wrong(uint8_t* a)
{
uint16_t b = 0;
a[b] = 0;
b[a] = 0;
}


int main()
{
size_t i;
uint8_t array[3] = {1, 2, 3};

youre_still_wrong(array);

for (i = 0; i < 3; ++i)
{
fprintf(stdout, "%d ", array[i]);
}
fprintf(stdout, "\n");

return 0;
}

Still prints 0 2 3 and not 0 0 3. You're wrong, just give up.

It is not. The compiler *needs* you to supply at least one type of integer in order to decide which one is the offset and which one isn't.

uint16_t a[3] = {1, 2, 3};
uint32_t *b = 0;

a[b] = 0; //Should work anyway if the compiler does not check for type as a pointer is essentially a number

//GCC:
//error: array subscript is not an integer
//a[b] = 0;

>The compiler *needs* you to supply at least one type of integer
That's not the same argument as claiming that integer width has an impact though.

For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type and the other shall have integer type. (Incrementing is equivalent to adding 1.

You can only have one side being an integer and one a pointer. It does not matter which order your operands are in, they will both produce the same result.

no shit one of the operands needs to be an integer type
what is your point even

How would you point to an arbitrary memory location without a pointer?

They will as long as it is a typed pointer and not a void pointer, as the standard states. And this is my point.

The absolute state of Sup Forums

Nowhere. These days you can write even full blown operating systems using only managed code.

talking about pointer _arithmetic_, not pointer as primitive

>talking about pointer _arithmetic_, not pointer as primitive
They go hand in hand though.

void foo(void* ptr)
{
char* cptr = ptr;
uint32_t* iptr = cptr + 1;
*cptr = 'a';
*iptr = 0xdeadbeef;
}


The array index equivalent of this would be

void foo(char* a)
{
a[0] = 'a';
#ifdef LITTLE_ENDIAN
a[1] = 0xef;
a[2] = 0xbe;
a[3] = 0xad;
a[4] = 0xde;
#else
a[1] = 0xde;
a[2] = 0xad;
a[3] = 0xbe;
a[4] = 0xef;
#endif
}


You tell me which one is easier to read and understand?

do you ever use iterator arithmetic in c++
now imagine you dont have iterators or operator overloading

How do you switch to protected mode again?

osdev.org

It's never necessary outside of really low level stuff, but I'm still gonna do shit like
int main(int argc, char *argv[])
{
while (--argc) handle_arg(*++argv);
}
Just because.

Does that wiki have even a single line of managed code?

when C programmers stop producing shitty intentionally obfuscated and broken code like this I will start taking them seriously

even K&R is full of shit like this, people pretend its smart. But really 99% of programmers understand it but have outgrown that kind of childish thing.

>broken
I could give you the others, but not this.

there is a data structure pattern (I don't remember what's it called) used in the Linux kernel where instead of wrapping your values in a node struct you embed the node struct inside your value struct and use marcos defined for the data structure operate with the list
it's very effective as it mimics templates and removes the indirection and extra allocation created by the use of void pointers
it requires pointer arithmetic to work

It's just called list, because that's what it is. It's in include/linux/list.h

the pattern of embedding the metadata of the data structure in your value structure instead of the other way around can be applied to many data structures and it has a name which I forgot

it's a blatant pissing contest

> it has a name which I forgot
intrusive x

thank you so much!

y-you're welcome

void foo(void* ptr) {

(char) *ptr = 'a';
(uint32_t) *(ptr + 1) = 0xDEADBEEF;
}

this one.

clang-tidy gives a readability-misplaced-array-index warning with this

English please, we are not in 1950 anymore!

Why would we care what a linter gives you? That's only for making the code presentable, not correct.

void
foo(void *ptr)
{
char *ptr = 'a';
uint32_t *(ptr + 1) = 0xDEADBEEF;
}

a pointer is a fucking address. if you do pointer+1 you are moving to another memory location.

>Why would we care what a linter gives you?
For making the code presentable
>That's only for making the code presentable, not correct.
I never said it made the code incorrect. Why are you so defensive?

>I never said it made the code incorrect.
So it has no bearing on the validity of the code.

>Why are you so defensive?
There was nothing to defend, it was pure offense.

>So it has no bearing on the validity of the code
Again, I never said it did

you dumb fucker