0

An old colleague in my firma write C sentences like the next:

#include <stdio.h>
#include <stdint.h>

typedef struct {
    char word;
    int age;
} Info;

typedef struct {
    Info info[1];
}TCBInfoTab;

int main(int argc, char *argv[]){

    const size_t storesize = (uintptr_t) &(((TCBInfoTab *) 0)->info[0]);      <-------------Here

    return 1;
}

Please, any volunteer would like to explain me what make the sentence: const size_t storesize = (uintptr_t) &(((TCBInfoTab *) 0)->info[0]);

I only understand a cast to a TCBInfoTab from 0, then get the address of a info[0] parameter (but from 0???!!!)and cast it to uintptr_t and finaly stores it in a size_t WTF???

Thanks in advance

Jos
  • 23
  • 4
  • 7
    It seems to be doing what [`offsetof`](https://en.cppreference.com/w/c/types/offsetof) is doing. – Some programmer dude Mar 31 '21 at 16:46
  • 1
    You can't dereference a `0` pointer, but this is not dereferencing it. It's just getting another address relative to it. – Barmar Mar 31 '21 at 16:47
  • Nominally, it says to give the address of the first element of `info` in a `TCBInfoTab` structure that was itself located at address zero. Since the first element of `info` in such a structure starts at the start of a structure, its address would also be zero. So `storesize` would be zero. That seems useless. Technically, a C compiler could produce other results, because there is no actual object at that address in the C model, so the pointer arithmetic implicit in `[0]` is not defined, and the conversion to `uintptr_t` is implementation-defined. But any other result from this is also useless. – Eric Postpischil Mar 31 '21 at 16:52
  • @Barmar: Not a duplicate, because this code contains pointer arithmetic (due to the definition of the subscript operator) that is not defined. – Eric Postpischil Mar 31 '21 at 16:55
  • @EricPostpischil I'll take your word for it, but isn't `&foo[0]` the same address as `&foo`? – Barmar Mar 31 '21 at 16:57
  • Thank you very much all – Jos Mar 31 '21 at 17:02
  • 1
    @Barmar: `&foo[0]` is, according to the specification of `&`, `foo + 0`. Then you are doing arithmetic for a thing that does not exist. This hack for taking the address of a structure member is questionable in the first place; I do not think it is defined by the standard, but compilers may allow it. But doing pointer arithmetic goes beyond that. Again, a compiler may allow it, but it is a separate question from the plain member hack. I think the notional pointer that results from `foo` is invalid, so the behavior of `+` is undefined by the C standard. – Eric Postpischil Mar 31 '21 at 17:07
  • Thank you very much all. @Barmar, Moment, if foo is a pointer to an array, foo is a pointer to the first element, *foo the first element *(foo+1) the second, &foo, a pointer to the pointer foo – Jos Mar 31 '21 at 17:14
  • But there is more: looking close to my colleague code, he made: const size_t storesize = (uintptr_t) &(((TCBInfoTab *) 0)->info[100]); (in my example I used 0). Total no sense, the info element array have only an element. Neverless, when I debug, I obtain: storesize = 9696 – Jos Mar 31 '21 at 17:59
  • 9696 is not divisible by 99 or 100, but by 101. Since the expression you show us is the same as some implementations of the macro `offsetof()`, I assume that the index is 101, not 100, and the size of a single `Info` is 96 bytes, or you have another structure member before `info[1]`. – the busybee Mar 31 '21 at 18:26

1 Answers1

2

The code may be an attempt to calculate the offset of an element of an array member of a structure. It does not quite make sense in the limited context shown in the question, but if we assume the structure may have other members and the array element of interest is not always zero but some member i, then it makes more sense. However, the expression shown in the question is flawed.

The C standard provides a way to calculate the offset of a structure member, the offsetof macro, declared in <stddef.h>. However, this is is for a structure member, not an element of an array of a member of a structure. But we can use arithmetic to calculate the desired offset.

The offset of element i in the array info of a structure of type TCBInfoTab is:

offsetof(TCBInfoTab, info) + i * sizeof *((TCBInfoTab *) NULL)->info

This expression has type size_t.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312