Is there a way to understand a behaviour whether it's undefined-unspecified-implementation defined?
If we can't know, how can I avoid using these statements?
Also, if there is a source that I can find these kind of common UB's can you share?
Is there a way to understand a behaviour whether it's undefined-unspecified-implementation defined?
If we can't know, how can I avoid using these statements?
Also, if there is a source that I can find these kind of common UB's can you share?
The 2018 C standard lists unspecified behaviors in annex J.1, undefined behaviors in J.2, and implementation-defined behavior in J.3. Approximately 350 items are listed, and some of them are multitudinous, such as the first in the undefined category: “A ‘shall’ or ‘shall not’ requirement that appears outside of a constraint is violated (Clause 4).“ The word “shall” appears in 300 sections (I do not know how many are constraints). (Annex J is informative but refers to the normative parts of the standard.)
So even if we listed all the items here, risking violating copyright law, it is not feasible to work day to day by memorizing the cases or even by referring to the list regularly while writing code. Skilled practitioners learn core things that are well defined (which involves unlearning things taught improperly in educational courses) and learn to refer to the standard or other reference material when dealing with things that may not be well defined.
For the most part, a skilled practitioner writes code that is well defined: We have simple objects, simple control flow, pointers are used in “normal” ways, array sizes are respected, and so on. A programmer learns when they need to reflect on something questionable, as when signedness issues may creep into code (as when an unsigned character type is promoted to a signed int
) or a need arises to do some “funny business” with pointers. The ability to do this is, for the most part, not explicitly studied; it is acquired with experience.
One does have to become familiar with the most important rules and learn to write code that one knows is defined because one can cite, at least generally, the rules that make it defined. After a student’s initial false bravado has been shaken and they have started to learn the formal rules of the language (in contrast with learning from tutorials that gloss over the rules), they can start to build something of a deduction-based knowledge of the C rules. Then the way you program is to write code that you know works because you know the rules—and when you reach a point where you are not sure, you look up the rules, in the C standard or other documentation. That causes a consider amount of work at first; once has to look up some rules many times before they are fully remembered or even well understood. But it gets easier.