How should I correctly understand the concept of effective types in the C11 standard?

Frankly speaking, the concepts of effective types and strict aliasing in the C11 standard are quite a headache for me to read.Now, I have some of my own understanding of the concept of effective types, and at the same time, I also have some doubts.
The C11 standard introduces effective types as follows. I will extract some key sentences from it and divide them into multiple paragraphs to facilitate raising my questions later:(Perhaps my question is very long. I would be very grateful if you could finish reading it.)
6.5 p6:

1.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.

2.For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access.

87) Allocated objects have no declared type.

For the sentence “For all other accesses to an object having no declared type“, the only situation I can think of is “storing a value into an object without declared type through an lvalue having character type”.
The following code example:

int main(void)
{
    unsigned char* a=malloc(sizeof(unsigned char));
    *a=50;//An object without declared type now has effective type unsigned char
    signed char* b=(signed char* )a;
    signed char c=*b;//An object without declared type now has effective type signed char,
                     //rather than unsigned char,because "the effective type of the object 
                     //is simply the type of the lvalue used for the access."
}

and:

int main(void)
{
    unsigned int* a=malloc(sizeof(unsigned int));
    *a=50;//An object without declared type now has effective type unsigned int
    signed int* b=(signed int* )a;
    signed int c=*b;//An object without declared type now still has effective type unsigned int,
                    //rather than signed int.                 
}

I think the example I gave also reflects the difference between the sentences
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.
and
the effective type of the object is simply the type of the lvalue used for the access.
in C11.
Now, my questions are as follows:

1.Am I wrong in my analysis of the above two pieces of code? If so, then what example can reflect the differences between the two sentences I excerpted from the above C11?

2.If my analysis is correct, could you give an another example that reflects the differences between the above two paragraphs in a completely different way?

3.For the sentence “For all other accesses to an object having no declared type“,What other situations are there?

4.Thank you again. It must take you some effort to read and answer my questions. In return, I wish you a happy day.

You omitted important sentences in C 2011 6.5 6. Adding letters to label them, the sentences in that paragraph are:

(a) The effective type of an object for an access to its stored value is the declared type of the object, if any.

(b) 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.

(c) 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.

(d) For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access.

1.Am I wrong in my analysis of the above two pieces of code? If so, then what example can reflect the differences between the two sentences I excerpted from the above C11?

Most of it looks okay, but this line is incorrect:

*a=50;//An object without declared type now has effective type unsigned char

The type of a is unsigned char *, so *a is an lvalue with character type, so this does not qualify for (b). Since 50 is an int constant, then, strictly speaking, this does not qualify for (c) since a value has not been copied into *a from an object. (The standard’s definition of effective type lets us down here, since it is generally understood that copying bytes into a suitably aligned buffer from a file or communication protocol can effectively reproduce an object that existed previously in another program but does not exist in the currently executing program. This ought to extend to manually creating objects by putting hard-coded values into their bytes.)

2.If my analysis is correct, could you give an another example that reflects the differences between the above two paragraphs in a completely different way?

Not at the moment.

3.For the sentence “For all other accesses to an object having no declared type”,What other situations are there?

(a) eliminates declared type, leaving only non-declared types. (b) eliminates stores with a non-character type, leaving both reads with any type and stores with a character type. (c) eliminates stores with a character type from objects with effective types, now leaving both reads with any type and stores with a character type not coming from objects with effective types.

Note that (b) and (c) also grant their effective types to subsequent accesses that do not modify the value. Thus, the remaining accesses for (d) are:

  • Reads with any type that do not occur after (b) and (c). This will include reads of uninitialized memory and reads of memory that was give values using byte accesses and values that did not come from an object with an effective type.
  • Stores with a character type not coming from an object with an effective type.

The major import of the effective types rules is this: If the compiler can observe that some region of memory has an effective type, because it was declared with that or an object of that type was stored or copied into it, then it is allowed to conclude that that region of memory will retain that type until changed. In particularly, the compiler may conclude that memory accesses using a different type will not overlap this object unless permitted by the aliasing rules.

For example, absent outside complications, if we have a char *p pointing to allocated memory and a float *q, and the compiler can see you have copied an int into the memory at p, it may conclude the statement *q = 3.5f; does not change any of the sizeof (int) bytes at p, because *q = 3.5f; should only write to a float, and a float should not overlap the int at p. From that conclusion, the compiler may optimize the code by moving the store to *q to a more desirable location in the program, even if that move crosses other statements where *p is being used.

3

TL;DR: You’re getting bogged down in the details. The overall picture is relatively simple: an allocated object is considered to have a type established by the type of the contents most recently written into it, except that you can always read or write the representation of any object via lvalues of character type without impacting that object’s (effective) type.


For the sentence “For all other accesses to an object having no declared type“, the only situation I can think of is “storing a value into an object without declared type through an lvalue having character type”.

That’s in part because you have taken those two sentences out of context. You need to look at the whole paragraph (C11 6.5/6):

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. 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. For all other accesses to an
object having no declared type, the effective type of the object is
simply the type of the lvalue used for the access.

The question to be answered with respect to any given access through an lvalue is “what is the effective type of the object?” We have these cases:

  1. The object has a declared type. Then the effective type is the declared type.

  2. The object has no declared type. That is, it is an allocated object, or possibly an object whose provenance is not described by the spec. Then there are these sub-cases:

    1. The access is a store, and the type of the lvalue used for access is not a character type. Then the effective type of the object for this access and for future ones that do not modify the value is the type of the lvalue.

    2. The access is a store, and the type of the lvalue used for access is a character type. Then the effective type for the purposes of this access only is the type of the lvalue. This primarily accommodates the general allowance for accessing the representation of objects via lvalues of character type. Do not neglect that this or any other access might be to just part of a larger allocated object. It does not have to be an access to the whole allocated object at once.

    3. The access is a read, and the effective type of the object is already established. Then the effective type for the purposes of this access is the already-established effective type. These are among the cases described by the “all future accesses that do not modify the value” clauses in the spec.

    4. The access is a read, and the effective type of the object is not otherwise established. Then the effective type for the purposes of this access only is the type of the lvalue. This case does not apply when the accessed object’s effective type has been established via a previous store or a previous copy from another object, because then it would not be an “other” access.

Turning now to your specific examples:

1.Am I wrong in my analysis of the above two pieces of code? If so, then what example can reflect the differences between the two sentences I excerpted from the above C11?

If I understand you correctly then yes, you are a bit wrong.

    unsigned char* a=malloc(sizeof(unsigned char));
    *a=50;//An object without declared type now has effective type unsigned char

*a has type unsigned char, which is a character type. Therefore, *a=50 effects a store via an lvalue of character type, to which your sentence 2 applies. The effective type of the accessed object is unsigned char for the purposes of this access, but unlike if it were sentence 1 that applied, that has no implications for future accesses. I take that to differ from your “now has”.

    signed char* b=(signed char* )a;
    signed char c=*b;//An object without declared type now has effective type signed char,
                     //rather than unsigned char,because "the effective type of the object 
                     //is simply the type of the lvalue used for the access."

Again, accessing the object via an lvalue of character type, read or write, makes that character type the effective type of the accessed object for the purposes of that access only. It does not give the accessed object a different effective type for the purposes of future accesses.

On the other hand,

    unsigned int* a=malloc(sizeof(unsigned int));
    *a=50;//An object without declared type now has effective type unsigned int

Yes. Your sentence 1 applies to this case. The store to the allocated object via *a, an lvalue of type unsigned int, makes the effective type of the allocated object unsigned int not only for the purposes of that store, but also for all subsequent accesses that do not modify the stored value.

    signed int* b=(signed int* )a;
    signed int c=*b;//An object without declared type now still has effective type unsigned int,
                    //rather than signed int.                 

No. The store via *a determined the effective type for future accesses that do not modify the value, such as this one. The effective type of the allocated object is still unsigned int. However, C allows access via an lvalue having “a type that is the signed or unsigned type corresponding to the effective type of the object” (paragraph 6.5/7), which is what you have here.

7

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật