how statement is executed in c++? - c++

I'm working on C++,
The following is a function call in C++,
argument = myFunction(argument);
What will be the value of argument variable passed to myFunction() call i.e. value assigned before call to the function or value returned from the myFunction() function call.

Due to temporal necessity, the value of argument before calling myFunction will be passed. This is simply because you don't have the return value yet.
The parameters to a function call have to be evaluated before the call. The order of evaluation between parameters is unspecified, but you only have one, so it is evaluated. Whatever it is at that point (before the call) is used, then the function is called. When the function returns, after being run, the return value is assigned to argument.

+1 - #peachykeen
Also may I add that if argument isn't assigned a value before being passed to myFunction then depending on the compiler and settings, argument's value may be indeterminate before use.
This means that it's value may not be null or zero (depending on type).

Value assigned BEFORE the call will be used inside the function.

Related

Why are there [in]'s in the function protoype of HINTERNET? [duplicate]

When reading documentation on functions from external libraries of different kinds I have always seen the documentation state that a variable has to be [IN/OUT]. Could someone give me a detailed understanding on how [IN/OUT] relates to parameters of a function being passed by reference or by value.
Here is an example of a function I have come across that tells me it needs an [IN/OUT] parameter:
Prototype:
ULONG GetActivationState( ULONG * pActivationState );
Parameters
Type: ULONG*
Variable: pActivationState
Mode: IN/OUT
This part applies to all types of paramters - most library interfaces try to be C compatible, so it is more common to pass parameters by pointer, rather than by reference.
IN: When a parameter is listed as IN it is a guarantee being offered by the interface that it won't modify that parameter. In my opinion, this is better conveyed by marking the parameter as const, then the language itself will prevent modifications to the value. If this parameter is being passed by value, it is inconsequential whether it is marked IN in the documentation (or const in the prototype) since the parameter is local to the function anyway. But to avoid copying it may be passed by reference or by pointer, in which case the const keyword becomes very important.
OUT: A parameter marked OUT usually means that the value of the parameter when it is being passed to the function is not of any importance. In fact, if it being passed by pointer, it may even be required to be NULL, and the function will allocate memory and pass a value back to you.
IN/OUT: An IN/OUT parameter usually indicates something where both the input and output values are meaningful. For instance, if you have a library function that fills a buffer, it may require you to pass a pointer to the buffer, along with another pointer indicating the length of the buffer. When the function returns, the second pointer may contain the actual number of bytes that have been written to the buffer.
This parameter is in/out because you provide a value that is used inside the function, and the function modifies it to inform you about something that happened inside the function. The usage of this function would be something like this:
ULONG activationState = 1; // example value
ULONG result = GetActivationState(&activationState);
note that you have to supply the address of the variable so that the function can get the value and set the value outside the function. For instance, the GetActivationState function can perform something like this:
ULONG GetActivationState(ULONG* pActivationState)
{
if (*pActivationState == 1)
{
// do something
// and inform by the modification of the variable, say, resetting it to 0
*pActivationState = 0;
}
// ...
return *pActivationState; // just an example, returns the same value
}
Note how:
The function accepts the parameter as a non-const pointer to an UINT. This means it may modify it.
The function can access the value you gave to the parameter by dereferencing it
The function can modify the parameter again by dereferencing it.
The calling function sees the activationState variable holding the new value (0 in this case).
This is an example of "pass by reference", which is performed by using pointers in C (and also with references in C++.)
Generally, things marked as IN/OUT will be passed via a non-const pointer or reference, allowing the function to modify the variable directly, as well as read it. Be sure to check the documentation to see if it expects the value to be set prior to passing it in.
Parameters marked as IN will be passed by value, or by constant pointer or constant reference, disallowing the function from modifying the variable.
C++ doesn't enforce OUT-only parameters, but generally they will be passed using non-const pointer or references, similar to IN/OUT.
If a parameter is OUT, it has to be passed by reference. A purely IN parameter would be usually passed by value or const reference, if the cost of copying is too high (nothing prevents the designed from passing it by reference, but it's not very good design IMHO). An IN/OUT parameter must be passed by reference.
I'm of a mixed mind regarding the use of in, out, and in/out.
Upside: When done properly, it communicates intent to the reader of the documentation.
Downside: Far too often it is not done properly. Those designations obviously are not a part of the language; they are either in comments or are in some document that is maintained separately from the code. I've seen far too many cases where a parameter was marked as "out" but the first thing done in the code with that parameter is to use it as a right-hand side value.
You can use by value (simply types) or by constant reference const & for input only parameters. Use non-const reference & or pointer * as in/out parameter to change the value of the variable. You can also use a pointer reference * & to allow you to change the address the actual pointer points to (in/out). As Dave Smith pointed out there is no out only parameter in C++.

What is the actual parameter list of member function created by the compiler?

I have a question about what value is passed to the C++ member function to invoke. When I disassemble a C++ member function like
void myClass::memberFunction() const;
I suppose it passed one implicit parameter this as the first and only parameter, but in fact, there could be two or more parameters passed.
I disassembled libobjc.A.dylib (iOS14.8-arm64e) with hopper. this function class_rw::method() const has no parameters, so I consider it pass only this pointer as the only parameter, but it has another (x1) parameter passed.
Then actual code is opensource on apple
https://opensource.apple.com/source/objc4/objc4-818.2/runtime/objc-runtime-new.mm.auto.html
And the snapshot is like
It seems the compiler auto-generated additional variables for this member function.
My question is that:
This should only happen when we put the implementation in the class declaration right?
This seems non-portable for classes that hides its implementation in another cpp file.
Is there a name for such an implicit added variable? I mean when we develop a compiler for c++, what do we call for such optimization?
From the ARM64 procedure call standard:
Result Return
The manner in which a result is returned from a function is determined by the type of that result:
If the type, T, of the result of a function is such that void func(T arg) would require that arg be passed as a value in a register (or set of registers) according to the rules in Parameter Passing, then the result is returned in the same registers as would be used for such an argument.
Otherwise, the caller shall reserve a block of memory of sufficient size and alignment to hold the result. The address of the memory block shall be passed as an additional argument to the function in x8. The callee may modify the result memory block at any point during the execution of the subroutine (there is no requirement for the callee to preserve the value stored in x8).
So this seems to be an example of the second type -- the return type method_array_t is something that is more than 16 bytes, so the caller allocates space for it and passes a pointer to that space as an extra argument.

How is it technically possible to have a null this pointer in a strack trace?

I have a core file where the application crashed inside a method which was called on a NULL-pointer:
class myclass{
myclass_impl* impl;
void func();
}
func(){impl->implFunc();}
The application crashes since the member impl is NULL. But the stracktrace ends in myclass_impl::implFunc() with *this beeing NULL.
How is that even possible?
Because the location of the function implFunc() is known. It has an address, therefore we know that we're inside it when we look at the call stack.
However, the this pointer that was used to call that function is set to 0 (or really, some undefined, but unallocated, value - depending on how it's used).
You can think of member methods like functions that take an implicit first argument as the this value (in fact, that's exactly what happens on many platforms). You don't need pointers to be valid in order to call a function. The call will at least reach the function, and thus place the function's location on the call stack (which is what is used to generate a backtrace), and what happens inside the function is up to whether or not you dereference that pointer.
Your scenario, then, means you called that function with the implicit first parameter being a NULL pointer. The function call itself succeeded, but the pointer being used inside the function (method) failed because you dereferenced a null pointer.

When should I use a reference?

Newbie here, I am reading some code, and I see sometimes the author used the reference in a function as
funca (scalar& a)
// Etc
Sometimes he just use
funcb (scalar a)
// Etc
What's the difference? Is using a reference a good habit that I should have?
Thank you!
If you call foo(scalar a), the argument a of type scalar will be COPIED from the caller and foo will have it's own COPY of the original object.
If you call foo(scalar &b), the argument b will be just a reference to the original object, so you will be able to modify it.
It's faster to pass an object by reference using the &name syntax, since it avoids creating a copy of the given object, but it can be potentially dangerous and sometimes the behavior is unwanted because you simply want an actual copy.
That being said, there's actually an option that disallows the ability to modify the original object for the called function yet avoids creating a copy. It's foo(const scalar &x) which explicitly states that the caller does not want the function foo to modify the object passed as an argument.
Optional reading, carefully:
There's also a way of passing an argument as a raw pointer which is very rare in modern C++. Use with caution: foo(scalar *a). The caller has got to provide the address of an object instead of the object itself in this scenario, so the caller would call foo(&a). For the called function foo to be able to modify the object itself in this case, it would need to dereference the pointer a, like this in foo: *a =. The star in front of the variable name in this case says that we don't want to modify the address that we have received (as a direct result of the calling function providing &a, that is, the address of the object a).
Passing a parameter by reference allows the called function to modify its argument in a way that will be visible to the caller after the function returns, while passing by value means that any changes will be limited in scope to the called function. Therefore passing by (non-const) reference typically signifies that the callee intends to modify the argument or, less commonly, use it as an additional "return value".
Additionally, passing by reference means that no copy of the parameter needs to be made; passing by value requires such a copy (which may be detrimental for the memory footprint or runtime performance of your application). For this reason you will often see arguments of class type being passed as a const reference: the callee does not intend to modify the argument but it also wants to avoid a copy being made. Scalar arguments are of very small size, so they do not benefit from this approach.
See also Pass by Reference / Value in C++.
Call by value (funcb (scalar a)) will give the function a copy of the argument, so changes made to the argument are not visible to the caller.
Call by reference (funcb(scalar& b)) means that the function operates directly on the argument, so any changes made are directly visible to the caller.
Whether or not call by reference is a good practice depends on the circumstances. If you need the function to modify the argument (and the modifications to be visible to the caller) you obviously want to use call by reference. If you don't want to modify the argument using non-const reference arguments is misleading (since the signature indicates the argument could be changed), so call by value is more apropriate here. Of course for more complex types call by value can have a non-trivial overhead. In these cases call-by-const-reference is preferable (funcc(const scalar& c))

what functions are called when passing value to function

In C++, if an object of a class is passed as a parameter into a function, the copy constructor of the class will be called.
I was wondering if the object is of nonclass type, what function will be called?
Similarly in C, what function is called when passing values or address of variables into a function?
Thanks and regards!
No function will be called; the bytes composing the object will simply be copied to the correct place for the callee (be that a location in memory or a register).
The copy constructor is only called if the object is being passed by value (and is a non-POD type). This is one of the reasons that it is common practice to pass objects by reference and const reference should you not wish the object to be changed by the function.
No function is called.
Since non-object types don't have methods, they are simply copied onto the stack to be used as-is by your function.
It depends on the implementation, but in some cases you may incur a function call if you are passing a floating-point value into a function expecting a value of integral type. (This is an implementation detail rather than part of the language, it's true, but it's no less worth taking account of because of that. And such conversions are often slow in any event, function call required or not.)