简体   繁体   中英

Cast int (*a)[4] to int *p

Is it legal to cast a pointer to an array of ints to an int pointer?

int arr[4];
int (*a)[4] = &arr; 
int *p = (int*)a;

C 2018 6.3.2.3 7 says we can convert an int (*)[4] to an int * :

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined…

The alignment is necessarily correct since an array of int must have the alignment required for an int .

However, the only thing the C standard says about the value resulting from this conversion is:

… when converted back again, the result shall compare equal to the original pointer.

This means that an int * can temporarily hold the value of an int (*)[4] . If we execute:

int arr[4];
int (*x)[4] = &arr;
int *y = (int *) x;
int (*z)[4] = (int (*)[4]) y;

then we know x == z is true because the standard tells us that. But we do not know what y is. Because the standard permits different types of pointers to have different representations (use the bits that represent their values in different ways), it is possible that y has no useful meaning as an int * . The C standard does not say the converted pointer can be used to access objects.

Most C implementations either support this deliberately or as an artifact of how they are designed. However, in terms of what the C standard specifies, no guarantee is given.

If the original pointer's initialized to either NULL or a valid pointer to an int[4] , then yes. Pointer casts must not violate alignment requirements lest you get UB . A cast such as what I've described won't violate such requirement ̶a̶n̶d̶ ̶f̶u̶r̶t̶h̶e̶r̶m̶o̶r̶e̶ ̶i̶t̶ ̶w̶i̶l̶l̶ ̶b̶e̶ ̶u̶s̶a̶b̶l̶e̶ ̶f̶o̶r̶ ̶d̶e̶r̶e̶f̶e̶r̶e̶n̶c̶i̶n̶g̶ ̶b̶e̶c̶a̶u̶s̶e̶ ̶i̶f̶ ̶t̶h̶e̶ ̶ ̶i̶n̶t̶(̶*̶a̶)̶[̶4̶]̶ ̶ ̶i̶s̶ ̶v̶a̶l̶i̶d̶ ̶a̶n̶d̶ ̶n̶o̶n̶n̶u̶l̶l̶ ̶t̶h̶e̶n̶ ̶t̶h̶e̶r̶e̶ ̶i̶n̶d̶e̶e̶d̶ ̶i̶s̶ ̶a̶n̶ ̶ ̶i̶n̶t̶ ̶ ̶a̶t̶ ̶ ̶(̶i̶n̶t̶*̶)̶a̶ ̶.

If you feel uneasy about pointer casts (as you should), you can effect the conversion in this case without casting by simply doing *a (will get int[4] which will decay to int* ) or a[0] or &a[0][0] or &(*a)[0] . That way, you can also dereference the result while adhering to the letter of the standard.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM