Is it undefined behavior to access the object representation of a pointer through a char*?

177 views Asked by At

I know this is weird question, but just bad curious.

char* ptr = 0;
strcpy( (char*) &ptr, "UB?");

This code means 'I will use the memory of ptr as a char array.' I think 'it's absolutely UB', but someone says 'it's not UB until you dereference'. It is not UB? How can this awful code not be UB?

3

There are 3 answers

1
Ian Abbott On BEST ANSWER

C17 ยง6.5 paragraph 6 includes:

The effective type of an object for an access to its stored value is the declared type of the object, if any. [...]

The effective type of the object denoted by ptr is char *.

Paragraph 7 includes:

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:

  • a type compatible with the effective type of the object,
  • a qualified version of a type compatible with the effective type of the object,
  • a type that is the signed or unsigned type corresponding to the effective type of the object,
  • a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
  • an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
  • a character type.

The object denoted by ptr is having its stored value accessed by an lvalue expression of character type (via the strcpy function which interprets characters as if they had type unsigned char). This is not UB.

13
Fe2O3 On

How could it be UB when this is legal (albeit horrible)?

union {
    char arr[4];
    char *ptr;
} trouble;

strcpy( trouble.arr, "UB?" );
0
supercat On

The Standard does not recognize any limitation on such constructs, provided the representation of the pointer is large enough to accommodate the string, but the CompCertC dialect requires that any storage which is used to hold data pointers must be accessed exclusively using lvalues of data-pointer types. Unlike the C Standard, it would allow void** to be used as a "pointer to any data pointer" type for purposes of accessing storage that is used to hold any data pointer, but it does not allow the use of unsigned char* or other similar types for such purposes.

I am unaware of any formally-specified dialect other than CompCertC that would not allow manipulation of pointer representations via unsigned char* or similar types.