Comment by uecker

1 month ago

You should read "7.1.4 1 Use of library functions". Also "calling a function" is not a side effect.

Thanks, I did read it! Things like footnote 236: "This means that an implementation is required to provide an actual function for each library function, even if it also provides a macro for that function", where macro is shown to use compiler builtin as an example.

Again, could you please explain how compiler can decide to remove call to a function in an external dynamically loaded library, that is not known at compile time, simply based on the name of the function (i.e. not because the call is unreachable)? I do not see any such language in the standard.

And yes, calling unknown function from a dynamically loaded library totally is a side effect.

  • > Again, could you please explain how compiler can decide to remove call to a function in an external dynamically loaded library, that is not known at compile time, simply based on the name of the function (i.e. not because the call is unreachable)? I do not see any such language in the standard.

    > And yes, calling unknown function from a dynamically loaded library totally is a side effect.

    The thing is that malloc/free aren't "unknown function[s]". From the C89 standard:

    > All external identifiers declared in any of the headers are reserved, whether or not the associated header is included.

    And from the C23 standard:

    > All identifiers with external linkage in any of the following subclauses (including the future library directions) and errno are always reserved for use as identifiers with external linkage

    malloc/free are defined in <stdlib.h> and so are reserved names, so compilers are able to optimize under the assumption that malloc/free will have the semantics dictated by the standard.

    In fact, the C23 standard explicitly provides an example of this kind of thing:

    > Because external identifiers and some macro names beginning with an underscore are reserved, implementations can provide special semantics for such names. For example, the identifier _BUILTIN_abs could be used to indicate generation of in-line code for the abs function. Thus, the appropriate header could specify

        #define abs(x) _BUILTIN_abs(x)
    

    > for a compiler whose code generator will accept it.

  • Only answering the "side effect" part as the rest was answered already.

    What a side effect is, is explained in "5.1.2.3". Calling function is only a side effect when the function contains a side effect, such as modifying an object, or a volatile access, or I/O.