Why Is F(I = -1, I = -1) Undefined Behavior

Why does printf(%f,0); give undefined behavior?

The "%f" format requires an argument of type double. You're giving it an argument of type int. That's why the behavior is undefined.

The standard does not guarantee that all-bits-zero is a valid representation of 0.0 (though it often is), or of any double value, or that int and double are the same size (remember it's double, not float), or, even if they are the same size, that they're passed as arguments to a variadic function in the same way.

It might happen to "work" on your system. That's the worst possible symptom of undefined behavior, because it makes it difficult to diagnose the error.

N1570 7.21.6.1 paragraph 9:

... If any argument is not the correct type for the corresponding
conversion specification, the behavior is undefined.

Arguments of type float are promoted to double, which is why printf("%f\n",0.0f) works. Arguments of integer types narrower than int are promoted to int or to unsigned int. These promotion rules (specified by N1570 6.5.2.2 paragraph 6) do not help in the case of printf("%f\n", 0).

Note that if you pass a constant 0 to a non-variadic function that expects a double argument, the behavior is well defined, assuming the function's prototype is visible. For example, sqrt(0) (after #include <math.h>) implicitly converts the argument 0 from int to double -- because the compiler can see from the declaration of sqrt that it expects a double argument. It has no such information for printf. Variadic functions like printf are special, and require more care in writing calls to them.

Behavior of C++ template function

Because there is a template argument deduction, reference collapsing happens. It is what Scott Meyers calls universal references. The U&& will actually become int &. There is a nice article and video about how it works and how it could be used.

Short int doesn't take the value

You have taken 6 variables a, b, c, d, e, f. The memory allocated by them are 2 bytes and the starting memory address are say for f 0x0, e 0x2, d 0x4, c 0x6, b 0x8, a 0xa

when you are doing
scanf("%d %d",&a,&b)
first value for a is written from memory location 0xa, occupying 4 bytes till 0xe. Then value for b is written starting from location 0x8 occupying 4 bytes till 0xc, thus overwriting memory location of a. same with other scanf. You will get different values if you change the order of memory location.

Please note output is dependent on the platform you are using hence undefined behaviour

Undefined reference to defined function using stdargs

template<> bool Call (asIScriptFunction*, string fml, ...);

This is not doing what you think it is doing. This is declaring a full template specialization of template <typename RET> Call with RET <- bool. You haven't defined it, and that old definition is out the door. Function template specialization is a weird beast, something probably best avoided.

What you are trying to do, I think, is to tell the compiler that you will be using an instantiation of Call. You don't need to do that. Just use it.

bool variable_name = Call<bool> (some_script, other_args);

Debug why does size_t not work as a data member?

Quite simply because in your first example the constructor uses n before it's ever initialized (actually, n never gets initialized).

So the line

while(cstr[n++])

is undefined behavior.

Try:

   test(const char *cstr) : n(0)  // <-- initialize n
{
size_t j=0;
while(cstr[n++])
;
//j = n;
}

Exception thrown in a constructor: is the destructor called?

The destructor will not be called because the foo object is not considered fully constructed until a constructor has finished executing (note that this means if you throw in a constructor that delegated to a different constructor then the destructor will be called). Throwing from a constructor is not undefined behaviour.

Should we always use auto&& for local variable

No. It will sometimes lead to undefined behavior.

void f()
{
string a{"a"};
string b{"b"};
auto&& c = move(a+b);
...
}

c will outlive the temporary produced by a+b. There are other ways to hit this issue also.

variadic function to function pointer

In C, these types are not compatible.

Section 6.2.7 of the C standard regarding "Compatible type and composite type" says the following regarding the compatibility of function pointers:

3 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 only one type is a function type with a parameter type list (a function prototype), the composite type is a function
    prototype with the parameter type list.
  • If both types are function types with parameter type lists, the type of each parameter in the composite parameter type list is the
    composite type of the corresponding parameters.

...

5 EXAMPLE Given the following two file scope declarations:

int f(int (*)(), double (*)[3]);
int f(int (*)(char *), double (*)[]);

The resulting composite type for the function is:

int f(int (*)(char *), double (*)[3]);

Section 6.7.6.3p15 states:

For two function types to be compatible, both shall specify
compatible return types. Moreover, the parameter type
lists, if both are present, shall agree in the number of
parameters and in use of the ellipsis terminator;

corresponding parameters shall have compatible types. If one type
has a parameter type list and the other type is specified by a
function declarator that is not part of a function definition
and that contains an empty identifier list, the parameter list
shall not have an ellipsis terminator and the type of each parameter
shall be compatible with the type that results from the
application of the default argument promotions. If one type has a
parameter type list and the other type is specified by a function
definition that contains a (possibly empty) identifier list, both
shall agree in the number of parameters, and the type of
each prototype parameter shall be compatible with the type
that results from the application of the default argument
promotions to the type of the corresponding identifier. (In
the determination of type compatibility and of a composite
type, each parameter declared with function or array type is
taken as having the adjusted type and each parameter declared with
qualified type is taken as having the unqualified version of its
declared type.)

In your example:

int test(int, ...);

This function is compatible with the following:

int (*)();            // a function taking an unknown number of parameters and returns an int
int (*)(int, ...); // a function taking an int and variable parameters after and returns an int

But not:

int (*)(int, int, long);    // a function taking an int, an int, and a long, and returns an int

Because both function type specify a parameter list and because the number of parameters nor does the use of ellipsis agree, the types are not compatible. Attempting to call a function through an incompatible pointer invokes undefined behavior as per section 6.3.2.3p8:

A pointer to a function of one type may be converted to a pointer to a
function of another type and back again; the result shall compare
equal to the original pointer. If a converted pointer is used to call
a function whose type is not compatible with the referenced type, the
behavior is undefined.



Related Topics



Leave a reply



Submit