2

This is a follow up to this question.

When explaining my problem, I declared that allocated memory could be reused because it has no declared type, and I was told that it was incorrect C.

Here is a code example illustrating the question:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

struct Elt {
    int id;
    char name[32];
};

struct Elt2 {
    double val;
    char name[16];
};

static_assert(sizeof(struct Elt2) < sizeof(struct Elt), "Incorrect sizes");

int main() {
    struct Elt actual1 = { 1, "foo"};
    struct Elt2 actual2 = {2.0, "bar"};

    struct Elt* elt = malloc(sizeof(struct Elt));
    memcpy(elt, &actual1, sizeof(*elt));          // populates the allocated memory
    printf("elt: %d %s\n", elt->id, elt->name);
    struct Elt2 *elt2 = (void *) elt;             // declares a new pointer to a shorter type
    memcpy(elt2, &actual2, sizeof(*elt2));        // effective type is now struct Elt2
    printf("elt2: %g %s\n", elt2->val, elt2->name);
    //printf("elt: %d %s\n", elt->id, elt->name);    UB: storage now contains an Elt2 object
    free(elt);                                    // only legal use for elt
    return 0;
}

I believe that 6.5 Expression §6 of draft n1570 allows it:

The effective type of an object for an access to its stored value is the declared type of the object, if any.87) 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. If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one.

with note 87:

87) Allocated objects have no declared type.

Question:

Is reusing allocated memory for storing a different object that can fit in that memory conformant C?

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • *"allocated memory could be reused because it has no declared type, and I was told that it was incorrect C."* I have not found evidence that anyone would have said or implied that. – user694733 Feb 01 '18 at 11:40
  • Also, the question is "can I write my_malloc based on malloc", as it has always been expected in C tradition. Also, does the C tradition mean anything for the C std committee. (Same for C++.) – curiousguy Feb 02 '18 at 14:57

2 Answers2

1

If not, that would be catastrophic. Many people use such tricks to implement their own fine grained memory management on to of malloc.

So, yes, this is exactly what the paragraph in the standard that you are citing is about. Notice that it choses the words carefully. It says

If a value is stored into an object having no declared type ...

this property of having no declared type doesn't change through the lifetime of the object, so the provision applies at any time a new value is written into it.

If, for some weird reason the committee would have wanted to say that the effective type is only changeable once, they would have say something like

If a value is stored into an object having no effective type ...

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • Thank you for confirming my thoughts. But then the edit in my [referenced question](https://stackoverflow.com/q/48559902/3545273) does make sense: does `memcpy` from an array of character type into an allocated struct change the effective type into a character array or not? – Serge Ballesta Feb 01 '18 at 15:24
0

The only correct answer is one that is fully derived from the standard.

Without going through the standard, I would say, "Yes, your assumption is correct". I say that because without it, it would not be possible to implement your own memory manager. I think not even malloc could be implemented in C without it.

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41