Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explanation of "effective type"?

Tags:

c

I'm reading the C specification, which states in 6.5 Expressions

The effective type of an object for an access to its stored value is the declared type of the object, if any. If a value is stored into an object having no declared type through an lvalue having a type that is not a character type, then the type of the lvalue becomes the effective type of the object for that access and for subsequent accesses that do not modify the stored value.

Can anyone explain what this means? I've got a vague feeling that it has to do with pointers and malloc(), but that's as far as I can get without help from a lawyer...

Update based on answer: Can I safely do this?

struct point {
    int x;
    int y;
};

int main() {
    int *x = malloc(1000);
    *x = 10;
    printf("%d\n", *x);

    struct point *p = x;
    p->x = 5;
    p->y = 10;
    printf("%d %d\n", p->x, p->y);
}

I'm getting a warning, but it works in my case. Is it guaranteed to work?

like image 253
blue_note Avatar asked Jun 20 '19 16:06

blue_note


1 Answers

When you declare a variable of a given type, it refers to an underlying object of that type, so the object's effective type is the type of the associated variable.

Where things get a little fuzzy is when malloc comes into play. Memory returned from malloc has no effective type. For example:

int *x = malloc(sizeof(int));

Assuming an int is 4 bytes in size, x now points to 4 bytes of memory with no effective type. This memory gets an effective type when assigned to:

*x = 123;

Now those bytes have an effective type of int.

In the case of your example, you allocate 1000 bytes, and initially these bytes have no effective type.

*x = 10;

This makes the first sizeof(int) bytes an object of type int.

struct point *p = x;

This should have a cast, but in the end it's OK because the first member of struct point has type int, and a pointer to a struct points to its first member.

p->x = 5;

This is therefore safe, because &p->x points to an object of type int, which matches the type of the lvalue p->x.

p->y = 10;

This is also safe, because the bytes pointed to by &p->y do not yet have an effective type, and the assignment causes the next sizeof(int) bytes to be an object of type int.

like image 146
dbush Avatar answered Oct 26 '22 22:10

dbush