Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C pointer arithmetic without object of structure

Tags:

c++

c

pointers

math

I think it is not possible in C but ask to verify this. Is it possible to make arithmetic between structure members without real variable of this type? For example:

typedef struct _s1 {   int a;   int b;   int c; } T1; 

I want to see the offset of "c" member compared to structure beginning. It is easy if I have variable:

T1 str;  int dist = (int)&str.c - (int)&str; 

But my structure is too big and it has no member in RAM (only in EEPROM). And I want to make some address calculations but not to define RAM member. I can do the job with structure pointer instead of structure variable (it will cost only 4 bytes) but the case is interesting for me.

like image 902
i486 Avatar asked Jan 30 '14 11:01

i486


People also ask

Does C support pointer arithmetic?

We can perform arithmetic operations on the pointers like addition, subtraction, etc. However, as we know that pointer contains the address, the result of an arithmetic operation performed on the pointer will also be a pointer if the other operand is of type integer.

What are the rules for pointer arithmetic?

When a pointer is incremented, it actually increments by the number equal to the size of the data type for which it is a pointer. For Example: If an integer pointer that stores address 1000 is incremented, then it will increment by 2(size of an int) and the new address it will points to 1002.

How is pointer arithmetic done in C?

p = p + 2; If you have two pointers that point to the same array, you can subtract one pointer from the other. This operation yields the number of elements in the array that separate the two addresses that the pointers refer to.

Why arithmetic operation Cannot be perform on a void pointer?

Since void is an incomplete type, it is not an object type. Therefore it is not a valid operand to an addition operation. Therefore you cannot perform pointer arithmetic on a void pointer.


2 Answers

Using offsetof you can make calculations between members without having to get hold of a variable of that type. All you need is the type itself and the name of the member.

A note why plain calculations are likely not to work out: data alignment. You do not know the amount of padding your compiler is going to throw at your structure and this can lead to very subtle mistakes or make seemingly correct calculations wrong if you change the structure.

like image 172
pmr Avatar answered Oct 12 '22 08:10

pmr


First off, you're casting the individual addresses to ints. I don't think that's such a good idea. an int is guaranteed to be at least 2 bytes or more in size, an address/pointer is generally 4 or 8 bytes. Casting these to int just doesn't sit right. If I were to cast them to anything, I'd probably use unsigned long for 32 bit systems, and unsigned long long for 64 bit. I'd use the latter to be safe.
That said, I wouldn't cast the addresses at all, and just use the offsetof macro.

Add #include <stddef.h> to your file, and use the offsetof macro, which casts the offset value to size_t type, not an int, mind you. It works simply by using 0 as the memory address of the struct, and then returns the address of the given member, giving the actual offset:

size_t offset = offsetoff(T1, c);                     //struct, member 

As Zack pointed out in his comment, the next part of the answer is somewhat irrelevant, but for the links it contains, and for completeness' sake, I'll just leave it here - as offsetof is required of all implementations:

Define the macro yourself, if you don't have stddef.h for some reason (which it ought to, because offsetof has been parto fo the standard for some time now: C89 and up), like so:

#ifndef offsetof #define offsetof(s, m) ((size_t)&(((s *) 0)->m)) #endif 

That ought to do the trick, but be wary: this implementation may cause undefined behaviour. How and why is explained here
I've taken the offsetof definition above from the stddef.h source I found here, so you may just download that file, and use it, instead of defining the macro in your own file but keep in mind that the offsetof you use is not 100% reliable.

Anyway, that's enough for now, more info on Google, but here's a couple of links:

  • GCC docs
  • related question on SO
  • another SO question
like image 30
Elias Van Ootegem Avatar answered Oct 12 '22 07:10

Elias Van Ootegem