はじめに(Introduction)
N3054 Working Draft, Standard for Programming Language C
C++ nは、ISO/IEC JTC1 SC22 WG14の作業原案(Working Draft)です。
公式のISO/IEC 9899原本ではありません。
ISO/IEC JTC1 SC22 のWG14を含むいくつかのWGでは、可能な限り作業文書を公開し、幅広い意見を求めています。
ISO/IEC JTC1 SC7からISO/IEC JTC1 SC22リエゾンとして、2000年頃、C/C++の品質向上に貢献しようとした活動をしていたことがあります。その頃は、まだISO/IEC TS 17961の原案が出る前です。Cの精神が優勢で、セキュリティ対策は補助的な位置付けでした。ISO/IEC TS 17961の制定と、C/C++のライブラリ類の見直しと、C++の進化はどんどん進んでいきます。
進化の具合が、どちらに行こうとしているかは、コンパイルて実行させてみないとわかりません。C/C++の規格案の電子ファイルは、そのままコンパイルできる形式であるとよいと主張してきました。MISRA-C/C++, CERTC/C++でも同様です。MISRA-C/C++は、Example Suiteという形で、コード断片をコンパイルできる形で提供するようになりました。
一連の記事はコード断片をコンパイルできる形にする方法を検討してコンパイル、リンク、実行して、規格案の原文と処理系(gcc, clang)との違いを確認し、技術内容を検討し、ISO/IEC JTC1 SC22 WG21にフィードバックするために用います。
また、CERT C/C++, MISRA C/C++等のコーディング標準のコード断片をコンパイルする際の参考にさせていただこうと考えています。CERT C++, MISRA C++が標準化の動きとの時間的なずれがあれば確認できれば幸いです。また、boostライブラリとの関連、Linux OS, 箱庭プロジェクト、g++(GCC), clang++(LLVM)との関係も調査中です。
何か、抜け漏れ、耳より情報がありましたらおしらせくださると幸いです。
最新規格はCN4950
背景(back ground)
C/C++でコンパイルエラーが出ると、途方にくれることがしばしばあります。
何回かに1回は、該当するエラーが検索できます。
ただ、条件が違っていて、そこでの修正方法では目的を達成しないこともしばしばです。いろいろな条件のコンパイルエラーとその対応方法について、広く記録することによって、いつか同じエラーに遭遇した時にやくに立つことを目指しています。
過去に何度か、自分のネットでの記録に助けられたことがあります。
また
https://researchmap.jp/joub9b3my-1797580/#_1797580
に記載したサイトのお世話になっています。
作業方針(sequence)
clangでは--std=c11, -std=C17 -std=c2xの3種類
gccでは-std=c11, -std=C17 -std=c2xの3種類
でコンパイルし、
1)コンパイルエラーを収集する。
2)コンパイルエラーをなくす方法を検討する。
コンパイルエラーになる例を示すだけが目的のコードは、コンパイルエラーをなくすのではなく、コンパイルエラーの種類を収集するだけにする。
文法を示すのが目的のコード場合に、コンパイルエラーをなくすのに手間がかかる場合は、順次作業します。
3)リンクエラーをなくす方法を検討する。
文法を示すのが目的のコード場合に、リンクエラーをなくすのに手間がかかる場合は、順次作業します。
4)意味のある出力を作る。
コンパイル、リンクが通っても、意味のある出力を示そうとすると、コンパイル・リンクエラーが出て収拾できそうにない場合がある。順次作業します。
1)だけのものから4)まで進んだものと色々ある状態です。一歩でも前に進むご助言をお待ちしています。「検討事項」の欄に現状を記録するようにしています。
$ docker run -v /Users/ogawakiyoshi/n4910/n3540:/Users/ogawakiyoshi/n4910/n3540 -it kaizenjapan/n3540 /bin/bash
読書感想文
CコンパイラによるC言語規格の読書感想文として掲載しています。
コンパイル実験が、CN3242に対する、gccとclangによる感想文だということご理解いただけると幸いです。
読書感想文は人間かAIだけが作るものとは限りません。
本(電子書籍を含む)を入力として、その内容に対する文字列を読書感想文として受け止めましょう。
元の文章をあり方、コンパイルできるように電子化しておくこと、コンパイラが解釈可能な断片の作り方など。
個人開発
Cコンパイラの試験を一人でもくもくとやっているのは個人開発の一つの姿です。
<この項は書きかけです。順次追記します。>
編纂器(Compiler)
clang --version
Debian clang version 14.0.6-++20220622053050+f28c006a5895-1~exp1~20220622173135.152
Target: x86_64-pc-linux-gnu Thread model: posix InstalledDir: /usr/bin
gcc --version
gcc (GCC) 12.1.0 Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
6. Language 6.2 Concepts CN3054:2022 (4) p34.c
算譜(source code)
// CN3054 Committee Draft, Standard for Programming Language C
// http://www.open-std.org/jtc1/sc22/wg14/docs/papers/2022/n3054.pdf
const char * n3054 = "6. Language 6.2 Concepts CN3054:2022 (4) p34.c";
// Debian clang version 14.0.5-++20220610033153+c12386ae247c-
// g++ (GCC) 12.1.0 Copyright (C) 2022 Free Software Foundation, Inc.
// Edited by Dr. OGAWA Kiyoshi. Compile procedure and results record.
// C++N3054:2022 Standard Working Draft on ISO/IEC 14882(0) sample code compile list
#include "N3054.h"
// 6.2.1 Scopes of identifiers
// An identifier can denote:
// — a standard attribute, an attribute prefix, or an attribute name; — an object; a function;
// — a tag or a member of a structure, union, or enumeration;
// — a typedef name;
// — a label name;
// — a macro name;
// — or, a macro parameter.
// The same identifier can denote different entities at different points in the program. A member of an enumeration is called an enumeration constant. Macro names and macro parameters are not considered further here, because prior to the semantic phase of program translation any occurrences of macro names in the source file are replaced by the preprocessing token sequences that constitute their macro definitions.
// For each different entity that an identifier designates, the identifier is visible (i.e., can be used) only within a region of program text called its scope. Different entities designated by the same identifier either have different scopes, or are in different name spaces. There are four kinds of scopes: function, file, block, and function prototype. (A function prototype is a declaration of a function.)
// A label name is the only kind of identifier that has function scope. It can be used (in a goto statement) anywhere in the function in which it appears, and is declared implicitly by its syntactic appearance (followed by a : and a statement).
// Every other identifier has scope determined by the placement of its declaration (in a declarator or type specifier). If the declarator or type specifier that declares the identifier appears outside of any block or list of parameters, the identifier has file scope, which terminates at the end of the translation unit. If the declarator or type specifier that declares the identifier appears inside a block or within the list of parameter declarations in a function definition, the identifier has block scope, which terminates at the end of the associated block. If the declarator or type specifier that declares the identifier appears within the list of parameter declarations in a function prototype (not part of a function definition), the identifier has function prototype scope, which terminates at the end of the function declarator. If an identifier designates two different entities in the same name space, the scopes might overlap. If so, the scope of one entity (the inner scope) will end strictly before the scope of the other entity (the outer scope). Within the inner scope, the identifier designates the entity declared in the inner scope; the entity declared in the outer scope is hidden (and not visible) within the inner scope.
// Unless explicitly stated otherwise, where this document uses the term "identifier" to refer to some entity (as opposed to the syntactic construct), it refers to the entity in the relevant name space whose declaration is visible at the point the identifier occurs.
// Two identifiers have the same scope if and only if their scopes terminate at the same point.
// Structure, union, and enumeration tags have scope that begins just after the appearance of the tag in a type specifier that declares the tag. Each enumeration constant has scope that begins just after the appearance of its defining enumerator in an enumerator list. An ordinary identifier that has an underspecified definition has scope that starts when the definition is completed; if the same ordinary identifier declares another entity with a scope that encloses the current block, that declaration is hidden as soon as the inner declarator is completed.31) Any other identifier has scope that begins just after the completion of its declarator.
// As a special case, a type name (which is not a declaration of an identifier) is considered to have a scope that begins just after the place within the type name where the omitted identifier would appear were it not omitted.
// Forward references: declarations (6.7), function calls (6.5.2.2), function definitions (6.9.1), identifiers (6.4.2), macro replacement (6.10.4), name spaces of identifiers (6.2.3), source file inclusion (6.10.2), statements and blocks (6.8).
// 6.2.2 Linkages of identifiers
// An identifier declared in different scopes or in the same scope more than once can be made to refer to the same object or function by a process called linkage32). There are three kinds of linkage: external, internal, and none.
// In the set of translation units and libraries that constitutes an entire program, each declaration of a particular identifier with external linkage denotes the same object or function. Within one translation unit, each declaration of an identifier with internal linkage denotes the same object or function. Each declaration of an identifier with no linkage denotes a unique entity.
// If the declaration of a file scope identifier for:
// — an object contains any of the storage-class specifiers static or constexpr;
// — or, a function contains the storage-class specifier static, then the identifier has internal linkage.33)
// For an identifier declared with the storage-class specifier extern in a scope in which a prior dec- laration of that identifier is visible34), if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.
// If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern. If the declaration of an identifier for an object has file scope and no storage-class specifier or only the specifier auto, its linkage is external.
// The following identifiers have no linkage: an identifier declared to be anything other than an object or a function; an identifier declared to be a function parameter; a block scope identifier for an object declared without the storage-class specifier extern.
// 31)That means, that the outer declaration is not visible for the initializer.
// 32)There is no linkage between different identifiers.
// 33)A function declaration can contain the storage-class specifier static only if it is at file scope; see 6.7.1. 34)As specified in 6.2.1, the later declaration might hide the prior declaration.
// If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined.
// Forward references: declarations (6.7), expressions (6.5), external definitions (6.9), statements (6.8).
// 6.2.3 Name spaces of identifiers
// If more than one declaration of a particular identifier is visible at any point in a translation unit, the syntactic context disambiguates uses that refer to different entities. Thus, there are separate name spaces for various categories of identifiers, as follows:
// — label names (disambiguated by the syntax of the label declaration and use);
// — the tags of structures, unions, and enumerations (disambiguated by following any35) of the keywords struct, union, or enum);
// — the members of structures or unions; each structure or union has a separate name space for its members (disambiguated by the type of the expression used to access the member via the . or -> operator);
// — standardattributesandattributeprefixes(disambiguatedbythesyntaxoftheattributespecifier and name of the attribute token) (6.7.12);
// — the trailing identifier in an attribute prefixed token; each attribute prefix has a separate name space for the implementation-defined attributes that it introduces (disambiguated by the attribute prefix and the trailing identifier token);
// — all other identifiers, called ordinary identifiers (declared in ordinary declarators or as enumera- tion constants).
// Forward references: enumeration specifiers (6.7.2.2), labeled statements (6.8.1), structure and union specifiers (6.7.2.1), structure and union members (6.5.2.3), tags (6.7.2.3), the goto statement (6.8.6.1).
// 6.2.4 Storage durations of objects
// An object has a storage duration that determines its lifetime. There are four storage durations: static, thread, automatic, and allocated. Allocated storage is described in 7.24.3.
// The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address.36), and retains its last-stored value throughout its lifetime37) If an object is referred to outside of its lifetime, the behavior is undefined. If a pointer value is used in an evaluation after the object the pointer points to (or just past) reaches the end of its lifetime, the behavior is undefined. The representation of a pointer object becomes indeterminate when the object the pointer points to (or just past) reaches the end of its lifetime.
// An object whose identifier is declared without the storage-class specifier thread_local, and either with external or internal linkage or with the storage-class specifier static, has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.
// An object whose identifier is declared with the storage-class specifier thread_local has thread storage duration. Its lifetime is the entire execution of the thread for which it is created, and its stored value is initialized when the thread is started. There is a distinct object per thread, and use of the declared name in an expression refers to the object associated with the thread evaluating the expression. The result of attempting to indirectly access an object with thread storage duration from a thread other than the one with which the object is associated is implementation-defined.
// An object whose identifier is declared with no linkage and without the storage-class specifier static has automatic storage duration, as do some compound literals. The result of attempting to indirectly access an object with automatic storage duration from a thread other than the one with which the object is associated is implementation-defined.
// 35)There is only one name space for tags even though three are possible.
// 36)The term "constant address" means that two pointers to the object constructed at possibly different times will compare equal. The address can be different during two different executions of the same program.
// 37)In the case of a volatile object, the last store need not be explicit in the program.
// For such an object that does not have a variable length array type, its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way. (Entering an enclosed block or calling a function suspends, but does not end, execution of the current block.) If the block is entered recursively, a new instance of the object is created each time. The initial representation of the object is indeterminate. If an initialization is specified for the object, it is performed each time the declaration or compound literal is reached in the execution of the block; otherwise, the representation of the object becomes indeterminate each time the declaration is reached.
// For such an object that does have a variable length array type, its lifetime extends from the declaration oftheobjectuntilexecutionoftheprogramleavesthescopeofthedeclaration.38) Ifthescopeis entered recursively, a new instance of the object is created each time. The initial representation of the object is indeterminate.
// A non-lvalue expression with structure or union type, where the structure or union contains a member with array type (including, recursively, members of all contained structures and unions) refers to an object with automatic storage duration and temporary lifetime.39) Its lifetime begins when the expression is evaluated and its initial value is the value of the expression. Its lifetime ends when the evaluation of the containing full expression ends. Any attempt to modify an object with temporary lifetime results in undefined behavior. An object with temporary lifetime behaves as if it were declared with the type of its value for the purposes of effective type. Such an object need not have a unique address.
// Forward references: array declarators (6.7.6.2), compound literals (6.5.2.5), declarators (6.7.6), function calls (6.5.2.2), initialization (6.7.10), statements (6.8), effective type (6.5).
// 6.2.5 Types
// The meaning of a value stored in an object or returned by a function is determined by the type of the expression used to access it. (An identifier declared to be an object is the simplest such expression; the type is specified in the declaration of the identifier.) Types are partitioned into object types (types that describe objects) and function types (types that describe functions). At various points within a translation unit an object type may be incomplete40) (lacking sufficient information to determine the size of objects of that type) or complete (having sufficient information)41).
// An object declared as type bool is large enough to store the values false and true.
// An object declared as type char is large enough to store any member of the basic execution char- acter set. If a member of the basic execution character set is stored in a char object, its value is guaranteed to be nonnegative. If any other character is stored in a char object, the resulting value is implementation-defined but shall be within the range of values that can be represented in that type.
// There are five standard signed integer types, designated as signed char, short int, int, long int, and long long int. (These and other types may be designated in several additional ways, as described in 6.7.2.)
// A bit-precise signed integer type is designated as _BitInt(N) where N is an integer constant expression that specifies the number of bits that are used to represent the type, including the sign bit. Each value of N designates a distinct type.42).
// There may also be implementation-defined extended signed integer types 43). The standard signed integer types, bit-precise signed integer types, and extended signed integer types are collectively called signed integer types 44).
// 38)Leaving the innermost block containing the declaration, or jumping to a point in that block or an embedded block prior to the declaration, leaves the scope of the declaration.
// 39)The address of such an object is taken implicitly when an array member is accessed.
// 40)An incomplete type can only be used when the size of an object of that type is not needed. It is not needed, for example, when a typedef name is declared to be a specifier for a structure or union, or when a pointer to or a function returning a structure or union is being declared. The specification has to be complete before such a function is called or defined.
// 41)A type can be incomplete or complete throughout an entire translation unit, or it can change states at different points within a translation unit.
// 42)Thus, _BitInt(3) is not the same type as _BitInt(4).
// 43)Implementation-defined keywords have the form of an identifier reserved for any use as described in 7.1.3.
// An object declared as type signed char occupies the same amount of storage as a "plain" char object. A "plain" int object has the natural size suggested by the architecture of the execution environment (large enough to contain any value in the range INT_MIN to INT_MAX as defined in the header <limits.h>).
// For each of the signed integer types, there is a corresponding (but different) unsigned integer type (designated with the keyword unsigned) that uses the same amount of storage (including sign information) and has the same alignment requirements. The type bool and the unsigned integer types that correspond to the standard signed integer types are the standard unsigned integer types. The unsigned integer types that correspond to the extended signed integer types are the extended unsigned integer types. In addition to the unsigned integer types that correspond to the bit-precise signedintegertypesthereisthetypeunsigned _BitInt(1),whichusesonebittorepresentthe type.Collectively,unsigned _BitInt(1)andtheunsignedintegertypesthatcorrespondtothebit- precise signed integer types are the bit-precise unsigned integer types. The standard unsigned integer types, bit-precise unsigned integer types, and extended unsigned integer types are collectively called unsigned integer types.45)
// The standard signed integer types and standard unsigned integer types are collectively called the standard integer types; the bit-precise signed integer types and bit-precise unsigned integer types are collectively called the bit-precise integer types; the extended signed integer types and extended unsigned integer types are collectively called the extended integer types.
// For any two integer types with the same signedness and different integer conversion rank (see 6.3.1.1), the range of values of the type with smaller integer conversion rank is a subrange of the values of the other type.
// The range of nonnegative values of a signed integer type is a subrange of the corresponding unsigned integer type, and the representation of the same value in each type is the same.46) The range of representable values for the unsigned type is 0 to 2N − 1 (inclusive). A computation involving unsigned operands can never produce an overflow, because arithmetic for the unsigned type is performed modulo 2N .
// There are three standard floating types, designated as float, double, and long double. 47) The set of values of the type float is a subset of the set of values of the type double; the set of values of the typedoubleisasubsetofthesetofvaluesofthetypelong double.
// There are three decimal floating types, designated as _Decimal32, _Decimal64, and _Decimal128. Respectively, they have the IEC 60559 formats: decimal3248), decimal64, and decimal128. Deci- mal floating types are real floating types. (Decimal floating types are a conditional feature that implementations need not support; see 6.10.9.3.)
// The standard floating types and the decimal floating types are collectively called the real floating types.
// There are three complex types, designated as float _Complex, double _Complex, and long double _Complex.49) (Complex types are a conditional feature that implementations need not support; see 6.10.9.3.) The real floating and complex types are collectively called the floating types.
// For each floating type there is a corresponding real type, which is always a real floating type. For real floating types, it is the same type. For complex types, it is the type given by deleting the keyword _Complex from the type name.
// 44)Any statement in this document about signed integer types also applies to the bit-precise signed integer types and the extended signed integer types, unless otherwise noted.
// 45)Any statement in this document about unsigned integer types also applies to the bit-precise unsigned integer types and the extended unsigned integer types, unless otherwise specified.
// 46)The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions.
// 47)See "future language directions" (6.11.1).
// 48)IEC 60559 specifies decimal32 as a data-interchange format that does not require arithmetic support; however, _Decimal32 is a fully supported arithmetic type.
// 49)A specification for imaginary types is in Annex G.
// Each complex type has the same representation and alignment requirements as an array type containing exactly two elements of the corresponding real type; the first element is equal to the real part, and the second element to the imaginary part, of the complex number.
// The type char, the signed and unsigned integer types, and the floating types are collectively called the basic types. The basic types are complete object types. Even if the implementation defines two or more basic types to have the same representation, they are nevertheless different types.
// NOTE 1 An implementation can define new keywords that provide alternative ways to designate a basic (or any other) type; this does not violate the requirement that all basic types be different. Implementation-defined keywords have the form of an identifier reserved for any use as described in 7.1.3.
// The three types char, signed char, and unsigned char are collectively called the character types. The implementation shall define char to have the same range, representation, and behavior as either signed charorunsigned char.50)
// An enumeration comprises a set of named integer constant values. Each distinct enumeration constitutes a different enumerated type.
// The type char, the signed and unsigned integer types, and the enumerated types are collectively called integer types. The integer and real floating types are collectively called real types.
// Integer and floating types are collectively called arithmetic types. Each arithmetic type belongs to one type domain: the real type domain comprises the real types, the complex type domain comprises the complex types.
// The void type comprises an empty set of values; it is an incomplete object type that cannot be completed.
// Any number of derived types can be constructed from the object and function types, as follows:
// — An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. The element type shall be complete whenever the array type is specified. Array types are characterized by their element type and by the number of elements in the array. An array type is said to be derived from its element type, and if its element type is T, the array type is sometimes called "array of T". The construction of an array type from an element type is called "array type derivation".
// — A structure type describes a sequentially allocated nonempty set of member objects (and, in certain circumstances, an incomplete array), each of which has an optionally specified name and possibly distinct type.
// — A union type describes an overlapping nonempty set of member objects, each of which has an optionally specified name and possibly distinct type.
// — A function type describes a function with specified return type. A function type is characterized by its return type and the number and types of its parameters. A function type is said to be derived from its return type, and if its return type is T, the function type is sometimes called "function returning T". The construction of a function type from a return type is called "function type derivation".
// — A pointer type may be derived from a function type or an object type, called the referenced type. A pointer type describes an object whose value provides a reference to an entity of the referenced type. A pointer type derived from the referenced type T is sometimes called "pointer to T". The construction of a pointer type from a referenced type is called "pointer type derivation". A pointer type is a complete object type.
// — An atomic type describes the type designated by the construct _Atomic(type-name). (Atomic types are a conditional feature that implementations need not support; see 6.10.9.3.)
// 50)CHAR_MIN, defined in <limits.h>, will have one of the values 0 or SCHAR_MIN, and this can be used to distinguish the two options. Irrespective of the choice made, char is a separate type from the other two and is not compatible with either.
// These methods of constructing derived types can be applied recursively.
// Arithmetic types, pointer types, and the nullptr_t type are collectively called scalar types. Array and structure types are collectively called aggregate types51).
// An array type of unknown size is an incomplete type. It is completed, for an identifier of that type, by specifying the size in a later declaration (with internal or external linkage). A structure or union type of unknown content (as described in 6.7.2.3) is an incomplete type. It is completed, for all declarations of that type, by declaring the same structure or union tag with its defining content later in the same scope.
// A complete type shall have a size that is less than or equal to SIZE_MAX. A type has known constant size if it is complete and is not a variable length array type.
// Array, function, and pointer types are collectively called derived declarator types. A declarator type derivation from a type T is the construction of a derived declarator type from T by the application of an array-type, a function-type, or a pointer-type derivation to T.
// A type is characterized by its type category, which is either the outermost derivation of a derived type (as noted above in the construction of derived types), or the type itself if the type consists of no derived types.
// Any type so far mentioned is an unqualified type. Each unqualified type has several qualified versions of its type52), corresponding to the combinations of one, two, or all three of the const, volatile, and restrict qualifiers. The qualified or unqualified versions of a type are distinct types that belong to the same type category and have the same representation and alignment requirements.53) An array and its element type are always considered to be identically qualified.54) Any other derived type is not qualified by the qualifiers (if any) of the type from which it is derived.
// Further, there is the _Atomic qualifier. The presence of the _Atomic qualifier designates an atomic type. The size, representation, and alignment of an atomic type need not be the same as those of the corresponding unqualified type. Therefore, this document explicitly uses the phrase "atomic, qualified, or unqualified type" whenever the atomic version of a type is permitted along with the other qualified versions of a type. The phrase "qualified or unqualified type", without specific mention of atomic, does not include the atomic types.
// A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.53) Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements. All pointers to structure types shall have the same representation and alignment requirements as each other. All pointers to union types shall have the same representation and alignment requirements as each other. Pointers to other types need not have the same representation or alignment requirements.
// EXAMPLE 1 The type designated as "float *" has type "pointer to float". Its type category is pointer, not a floating type. The const-qualified version of this type is designated as "float * const" whereas the type designated as "const float *" is not a qualified type — its type is "pointer to const-qualified float" and is a pointer to a qualified type.
// EXAMPLE 2 The type designated as "struct tag (*[5])(float)" has type "array of pointer to functionreturningstruct tag". Thearrayhaslengthfiveandthefunctionhasasingleparameter of type float. Its type category is array.
// Forward references: compatible type and composite type (6.2.7), declarations (6.7).
// 51)Note that aggregate type does not include union type because an object with union type can only contain one member at a time.
// 52)See 6.7.3 regarding qualified array and function types.
// 53)The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions.
// 54)This does not apply to the _Atomic qualifier. Note that qualifiers do not have any direct effect on the array type itself, but affect conversion rules for pointer types that reference an array type.
// 6.2.6 Representations of types
// 6.2.6.1 General
// The representations of all types are unspecified except as stated in this subclause.
// Except for bit-fields, objects are composed of contiguous sequences of one or more bytes, the number, order, and encoding of which are either explicitly specified or implementation-defined.
// Values stored in unsigned bit-fields and objects of type unsigned char shall be represented using a pure binary notation.
// NOTE 1 A positional representation for integers that uses the binary digits 0 and 1, in which the values represented by successive bits are additive, begin with 1, and are multiplied by successive integral powers of 2, except perhaps the bit with the highest position. (Adapted from the American National Dictionary for Information Processing Systems.) A byte contains CHAR_BIT bits, and the values of type unsigned char range from 0 to 2CHAR_BIT − 1.
// Values stored in non-bit-field objects of any other object type are represented using n×CHAR_BIT bits, where n is the size of an object of that type, in bytes. An object that has the value may be copied into anobjectoftypeunsigned char [n](e.g.,bymemcpy);theresultingsetofbytesiscalledtheobject representation of the value. Values stored in bit-fields consist of m bits, where m is the size specified for the bit-field. The object representation is the set of m bits the bit-field comprises in the addressable storage unit holding it. Two values (other than NaNs) with the same object representation compare equal, but values that compare equal may have different object representations.
// Certain object representations need not represent a value of the object type. If such a representation is read by an lvalue expression that does not have character type, the behavior is undefined. If such a representation is produced by a side effect that modifies all or any part of the object by an lvalue expression that does not have character type, the behavior is undefined.55) Such a representation is called a non-value representation.
// When a value is stored in an object of structure or union type, including in a member object, the bytes of the object representation that correspond to any padding bytes take unspecified values.56) The object representation of a structure or union object is never a non-value representation, even though the byte range corresponding to a member of the structure or union object may be a non-value representation for that member.
// When a value is stored in a member of an object of union type, the bytes of the object representation that do not correspond to that member but do correspond to other members take unspecified values.
// Where an operator is applied to a value that has more than one object representation, which object representation is used shall not affect the value of the result.57) Where a value is stored in an object using a type that has more than one object representation for that value, it is unspecified which representation is used, but a non-value representation shall not be generated.
// Loads and stores of objects with atomic types are done with memory_order_seq_cst semantics. Forward references: declarations (6.7), expressions (6.5), lvalues, arrays, and function designators (6.3.2.1), order and consistency (7.17.3).
// 6.2.6.2 Integer types
// For unsigned integer types the bits of the object representation shall be divided into two groups: value bits and padding bits. If there are N value bits, each bit shall represent a different power of 2 between 1 and 2N−1, so that objects of that type shall be capable of representing values from 0 to 2N − 1 using a pure binary representation; this shall be known as the value representation. The values of any padding bits are unspecified. The number of value bits N is called the width of the unsignedintegertype.Thetypeboolshallhaveonevaluebitand(sizeof(bool)*CHAR_BIT)-// padding bits. Otherwise, there need not be any padding bits; unsigned char shall not have any padding bits.
// 55)Thus, an automatic variable can be initialized to a non-value representation without causing undefined behavior, but the value of the variable cannot be used until a proper value is stored in it.
// 56)Thus, for example, structure assignment need not copy any padding bits.
// 57)It is possible for objects x and y with the same effective type T to have the same value when they are accessed as objects oftypeT,buttohavedifferentvaluesinothercontexts.Inparticular,if==isdefinedfortypeT,thenx == ydoesnotimply thatmemcmp(&x, &y, sizeof(T))== 0.Furthermore,x == ydoesnotnecessarilyimplythatxandyhavethesamevalue; other operations on values of type T might distinguish between them.
// For signed integer types, the bits of the object representation shall be divided into three groups: value bits, padding bits, and the sign bit. If the corresponding unsigned type has width N, the signed type uses the same number of N bits, its width, as value bits and sign bit. N − 1 are value bits and the remaining bit is the sign bit. Each bit that is a value bit shall have the same value as the same bit in the object representation of the corresponding unsigned type. If the sign bit is zero, it shall not affect the resulting value. If the sign bit is one, it has value −(2N−1). There need not be any paddingbits;signed charshallnothaveanypaddingbits.
// The values of any padding bits are unspecified. A valid object representation of a signed integer type where the sign bit is zero is a valid object representation of the corresponding unsigned type, and shall represent the same value. For any integer type, the object representation where all the bits are zero shall be a representation of the value zero in that type.
// The precision of an integer type is the number of value bits.
// NOTE 1 Some combinations of padding bits might generate non-value representations, for example, if one padding bit is a parity bit. Regardless, no arithmetic operation on valid values can generate a non-value representation other than as part of an exceptional condition such as an integer overflow, and this cannot occur with unsigned types. All other combinations of padding bits are alternative object representations of the value specified by the value bits.
// NOTE 2 The sign representation defined in this document is called two’s complement. Previous revisions of this document additionally allowed other sign representations.
// NOTE 3 For unsigned integer types the width and precision are the same, while for signed integer types the width is one greater than the precision.
// 6.2.7 Compatible type and composite type
// Two types are compatible types if they are the same. Additional rules for determining whether two types are compatible are described in 6.7.2 for type specifiers, in 6.7.3 for type qualifiers, and in 6.7.6 for declarators.58) Moreover, two complete structure, union, or enumerated types declared with the same tag are compatible if members satisfy the following requirements:
// — there shall be a one-to-one correspondence between their members such that each pair of corresponding members are declared with compatible types;
// — if one member of the pair is declared with an alignment specifier, the other is declared with an equivalent alignment specifier;
// — and, if one member of the pair is declared with a name, the other is declared with the same name.
// For two structures, corresponding members shall be declared in the same order. For two structures or unions, corresponding bit-fields shall have the same widths. For two enumerations, corresponding members shall have the same values; if one has a fixed underlying type, then the other shall have a compatible fixed underlying type. For determining type compatibility, anonymous structures and unions are considered a regular member of the containing structure or union type, and the type of an anonymous structure or union is considered compatible to the type of another anonymous structure or union, respectively, if their members fulfill the above requirements.
// Furthermore, two structure, union, or enumerated types declared in separate translation units are compatible in the following cases:
// — both are declared without tags and they fulfill the requirements above;
// — both have the same tag and are completed somewhere in their respective translation units and they fulfill the requirements above;
// — both have the same tag and at least one of the two types is not completed in its translation unit. 58)Two types need not be identical to be compatible.
// Otherwise, the structure, union, or enumerated types are incompatible.59)
// All declarations that refer to the same object or function shall have compatible type; otherwise, the behavior is undefined.
// A composite type can be constructed from two types that are compatible; it is a type that is compatible with both of the two types and satisfies the following conditions:
// — If both types are array types, the following rules are applied:
// • If one type is an array of known constant size, the composite type is an array of that size.
// • Otherwise, if one type is a variable length array whose size is specified by an expression that is not evaluated, the behavior is undefined.
// • Otherwise, if one type is a variable length array whose size is specified, the composite type is a variable length array of that size.
// • Otherwise, if one type is a variable length array of unspecified size, the composite type is a variable length array of unspecified size.
// • Otherwise, both types are arrays of unknown size and the composite type is an array of unknown size.
// The element type of the composite type is the composite type of the two element types.
// — If both types are function types, the type of each parameter in the composite parameter type list is the composite type of the corresponding parameters.
// — If one of the types has a standard attribute, the composite type also has that attribute.
// These rules apply recursively to the types from which the two types are derived.
// For an identifier with internal or external linkage declared in a scope in which a prior declaration of that identifier is visible60), if the prior declaration specifies internal or external linkage, the type of the identifier at the later declaration becomes the composite type.
// EXAMPLE Given the following two file scope declarations:
// The resulting composite type for the function is:
int f(int (*)(char *), double (*)[3]);
//Forward references: array declarators (6.7.6.2).
// 6.2.8 Alignment of objects
// Complete object types have alignment requirements which place restrictions on the addresses at which objects of that type may be allocated. An alignment is an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated. An object type imposes an alignment requirement on every object of that type: stricter alignment can be requested using the alignas keyword.
// A fundamental alignment is a valid alignment less than or equal to alignof(max_align_t). Funda- mental alignments shall be supported by the implementation for objects of all storage durations. The alignment requirements of the following types shall be fundamental alignments:
// — all atomic, qualified, or unqualified basic types;
// 59)A structure, union, or enumerated type without a tag or an incomplete structure, union or enumerated type is not compatible with any other structure, union or enum type declared in the same translation unit.
// 60)As specified in 6.2.1, the later declaration might hide the prior declaration.
int f(int (*)(char *), double (*)[3]);
int f(int (*)(char *), double (*)[]);
// — all atomic, qualified, or unqualified enumerated types;
// — all atomic, qualified, or unqualified pointer types;
// — all array types whose element type has a fundamental alignment requirement;
// — all types specified in Clause 7 as complete object types;
// — all structure or union types whose elements have types with fundamental alignment require- ments and none of whose elements have an alignment specifier specifying an alignment that is not a fundamental alignment.
// An extended alignment is represented by an alignment greater than alignof(max_align_t). It is implementation-defined whether any extended alignments are supported and the storage durations for which they are supported. A type having an extended alignment requirement is an over-aligned type.61)
// Alignments are represented as values of the type size_t. Valid alignments include only fundamental alignments, plus an additional implementation-defined set of values, which may be empty. Every valid alignment value shall be a nonnegative integral power of two.
// Alignments have an order from weaker to stronger or stricter alignments. Stricter alignments have larger alignment values. An address that satisfies an alignment requirement also satisfies any weaker valid alignment requirement.
// The alignment requirement of a complete type can be queried using an alignof expression. The typeschar,signed char,andunsigned charshallhavetheweakestalignmentrequirement.
// Comparing alignments is meaningful and provides the obvious results:
// — Two alignments are equal when their numeric values are equal.
// — Two alignments are different when their numeric values are not equal.
// — When an alignment is larger than another it represents a stricter alignment.
// 6.2.9 Encodings
// The literal encoding is an implementation-defined mapping of the characters of the execution character set to the values in a character constant (6.4.4.4) or string literal (6.4.5). It shall support a mapping from all the basic execution character set values into the implementation-defined encoding. It may contain multibyte character sequences (5.2.1.1).
// The wide literal encoding is an implementation-defined mapping of the characters of the execution character set to the values in a wchar_t character constant (6.4.4.4) or a wchar_t string literal (6.4.5). It shall support a mapping from all the basic execution character set values into the implementation- defined encoding. The mapping shall produce values identical to the literal encoding for all the basic execution character set values if an implementation does not define __STDC_MB_MIGHT_NEQ_WC__. One or more values may map to one or more values of the extended execution character set.
int main() {
// PR3(st.a,st.b,st.c,d);
printf("%s\n", n3054);
return EXIT_SUCCESS;
}
編纂・実行結果(compile and go)
$ clang p34.c -std=11 -o p34l -I. -Wall
6. Language 6.2 Concepts CN3054:2022 (4) p34.c
$ clang p34.c -std=17 -o p34l -I. -Wall
6. Language 6.2 Concepts CN3054:2022 (4) p34.c
$ clang p34.c -std=2x -o p34l -I. -Wall
6. Language 6.2 Concepts CN3054:2022 (4) p34.c
$ gcc p34.c -std=11 -o p34g -I. -Wall
p34.c:183:33: warning: mismatch in bound 1 of argument 2 declared as 'double (*)[]' [-Warray-parameter=]
183 | int f(int (*)(char *), double (*)[]);
| ^~~~~~~~~~~~
p34.c:174:24: note: previously declared as 'double (*)[3]'
174 | int f(int (*)(char *), double (*)[3]);
| ^~~~~~~~~~~~~
6. Language 6.2 Concepts CN3054:2022 (4) p34.c
$ gcc p34.c -std=c17 -o p34g -I. -Wall
p34.c:183:33: warning: mismatch in bound 1 of argument 2 declared as 'double (*)[]' [-Warray-parameter=]
183 | int f(int (*)(char *), double (*)[]);
| ^~~~~~~~~~~~
p34.c:174:24: note: previously declared as 'double (*)[3]'
174 | int f(int (*)(char *), double (*)[3]);
| ^~~~~~~~~~~~~
6. Language 6.2 Concepts CN3054:2022 (4) p34.c
$ gcc p34.c -std=c2x -o p34g -I. -Wall
p34.c:183:33: warning: mismatch in bound 1 of argument 2 declared as 'double (*)[]' [-Warray-parameter=]
183 | int f(int (*)(char *), double (*)[]);
| ^~~~~~~~~~~~
p34.c:174:24: note: previously declared as 'double (*)[3]'
174 | int f(int (*)(char *), double (*)[3]);
| ^~~~~~~~~~~~~
6. Language 6.2 Concepts CN3054:2022 (4) p34.c
検討事項(agenda)
gccのみ警告の理由を説明する。
応用例1 MISRA C/C++
MISRA C まとめ #include
MISRA C++ 5-0-16
応用例2 CERT C/C++
SEI CERT C++ Coding Standard AA. Bibliography 確認中。
MISRA C/C++, AUTOSAR C++, CERT C/C++とC/C++工業標準をコンパイルする
自己参考資料(self reference)
関連する自己参照以外は、こちらの先頭に移転。
C言語(C++)に対する誤解、曲解、無理解、爽快。
C言語教育はCコンパイラの写経で
C2011コンパイル一覧@researchmap
https://researchmap.jp/jownvh0ye-1797580/#_1797580
[C][C++]の国際規格案の例題をコンパイルするときの課題7つ。
C Puzzle Bookの有り難み5つ、C言語規格及びCコンパイラの特性を認識
dockerにclang
docker gnu(gcc/g++) and llvm(clang/clang++)
コンパイル用shell script C版(clangとgcc)とC++版(clang++とg++)
astyle 使ってみた
<この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。>
文書履歴(document history)
ver. 0.01 初稿 20221013
ver. 0.02 ありがとう追記 20230622
最後までおよみいただきありがとうございました。
いいね 💚、フォローをお願いします。
Thank you very much for reading to the last sentence.
Please press the like icon 💚 and follow me for your happy life.