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
C++ How Is Release-And-Acquire Achieved on X86 Only Using Mov
When to Make a Type Non-Movable in C++11
Why Does a C/C++ Compiler Need Know the Size of an Array at Compile Time
Get Absolute Value Without Using Abs Function Nor If Statement
Initializing Default Values in a Struct
Difference Between Creating Object with () or Without
Finding Out the CPU Clock Frequency (Per Core, Per Processor)
Do I Need to Close a Std::Fstream
Why Does Everybody Use Unanchored Namespace Declarations (I.E. Std:: Not ::Std::)
Why Is My Object Not Being Copied When Move Constructor Is Deleted
Compare Double to Zero Using Epsilon
C/C++ MACro/Template Blackmagic to Generate Unique Name
Why Doesn't Emplace_Back() Use Uniform Initialization
Compiling Cuda Code in Qt Creator on Windows
How to Print Utf-8 Strings to Std::Cout on Windows
How to Prevent Stack Allocation of an Object and Only Allow It to Be Instantiated with 'New'