for swap function we have two choice:
ref-style:
void swap (int &a, int &b)
{
int temp;
temp = b;
b = a;
a = temp;
}
and pointer-style:
void swap (int *a, int *b)
{
int temp;
temp = *b;
*b = *a;
*a = temp;
}
ref-style absolutely legal but pointer-style have some issue, when we try to use
this function variables pass by value not by reference-even they are pointers-
in fact we try to use memory of a local variable outside its function,
and may by in some day in some machine we have undefined behavior ,also the code works for examples:
In this code:
main()
{
//
{
int i=12;
int *j=&i;
}
//in this area, there is not variables i and j, but phisically threre is
// unsafe-relationship between this address: &i and what point to (12) ,
//any more logic according to this assumtion may be work
//but not safe -in the scene of undefined behavior-
I don't know where you got the sentence about outside a function from. You shouldn't trust them, since that sentence is wrong.
It should be "accessing a local variable or a parameter after the function has returned invokes undefined behavior". (These are my own words.)
To get the official wording, look in the C++ standard. The keywords to look for are lifetime, storage duration and undefined behavior.
Related
I was messing around with memory allocation. I was testing to see that, like Java, this program with give an exception.
int main() {
int* a = nullptr;
int b = *a;
std::cout << b;
}
Which indeed it does. Then I tested using malloc as a pointer to a, but not initializing a.
int main() {
int* a = (int*) malloc(sizeof(int));
int b = *a;
std::cout << b;
}
However, instead of throwing an exception, it prints out a seemingly random number in -842150451. I even tried replacing int with long:
int main() {
long* a = (long*) malloc(sizeof(long));
long b = *a;
std::cout << b;
}
However I got the same result. Then I tried it with short:
int main() {
short* a = (short*) malloc(sizeof(short));
short b = *a;
std::cout << b;
}
Then instead of the previous result, I got -12851. And it continued like this for every primitive type I could think of. What I want to know is, where are these numbers coming from and why these numbers specifically?
-842150451 is the two's complement representation of the value 0xCDCDCDCD, which is a common Visual Studio debugger value for heap-allocated uninitialized memory.
Uninitialized variables or memory have indeterminate values from the C++ specifications perspective, and using such values lead to undefined behavior. If you remember this, and always initialize such values or memory then you'll be alright.
All of your erroroneous programs have what's technically called undefined behaviour. Which means the behaviour of the program is unconstrained by the C++ standard, and therefore it's wrong to expect any particular outcome when you run your code.
C++ is quite unlike Java in this regard which specifies precise behaviours for most situations.
I had a simple question and was hoping for the underlying logic behind passing by reference.
Here's one code (let's call it Code1):
void fn(int& a)
{
a = 6;
}
int main()
{
int b = 5;
fn(b);
cout << b;
}
Here's another code (Code2):
void fn(int* ptr)
{
*ptr = 6;
}
int main()
{
int b = 5;
fn(&b);
cout << b;
}
And a pass by value code (Code 3):
void fn(int a)
{
a = 6;
}
int main()
{
int b = 5;
fn(b);
cout << b;
}
Here goes my question. Intuitively, I see that while passing by value (Code3), the values are copied ie a would just have taken/copied into itself the value of b. Thus, as a general rule, I see that value passed is just copied always to the called function (here fn). Even with the pointer code (ie Code2), the first line of Code 2 ensures that int *ptr = &a;
I don't understand how this would work in Code1. Saying that &a = b makes no sense. Is this an exception, or does this fit into a rule that is consistent with the cases discussed in the paragraph above?
Thanks!
In this function:
void fn(int &a) {
a=6;
}
the term "&a" does not mean "the address of the variable a". It means "a reference called a". Code 1 and Code 2 are effectively the same (but note that the function in Code 2 can be passed an invalid pointer, which is (almost) impossible for Code 1).
For most intents and purposes, a reference is just a pointer in disguise. Different syntax, same effect (mostly).
Conceptually, in your first case what happens is that the same variable has two labels: b, visible within the scope of main(); and a, visible within the scope of fn.
You don't have to worry about what the compiler does "behind the scenes" to implement this concept.
If you mentally promote the compiler's "behind the scenes" actions to actually being imagined principles of C++, e.g. "the reference is a pointer in disguise", then it leads you to get confused about what is actually a pretty simple concept: the ability to give multiple names to a variable.
It is nothing special being a function parameter; e.g. you could write in main():
int a;
int &c = a;
which is exactly equivalent to:
int c;
int &a = c;
In both cases there is an int variable with two labels, a and c.
When I compile this code it says "error C4700: uninitialized local variable 'b' used". I'm not sure what I have to do now to fix this problem. I'm neither an IT student or technican but I very like to learn C++ and I'm learning it by myself. I've been on this for 1 day.
Many thanks
#include <stdio.h>
#include <iostream>
//A.
//1--
void InputArray(int *a, int &n)
{
printf("Insert n = ");
scanf("%d", &n);
a = new int[n];
for (int i=0; i<n; i++)
{
printf("Enter the key's a[%d] values: ", i);
scanf("%d",&a[i]);
}
}
void main()
{
int *b, m;
InputArray(b, m);
}
b is passed by value, which means a copy will be made, but since it's not initialized, you get the warning. Simply initialize it:
int *b = nullptr;
or
int *b = NULL;
If you want the function to modify the caller's variable, then pass by reference:
void InputArray(int *&a, int &n)
^
Your version passes the uninitialised pointer by value; the function modifies a local copy of it, but leaves b in its uninitialised state.
The pointers are not default initialized, so your variable b is uninitialized, this is the source of error. You have to initialize this variable to fix this:
void main()
{
int *b = NULL, m;
InputArray(b, m);
}
After you fix this there is additional problem in your code. It seems from the way you call a function that you expect to persistently change pointer b passed into it, so that b will point into memory allocated with new after function returned. But you pass a pointer by value what means changes made in function will not be reflected in original variable b which will still point to what it pointed before the call to a function. (the array will be allocated inside function and will stay in memory after function returned but you will leak this memory as b won't point into it). To fix this you have to pass pointer by reference:
void InputArray(int*& a, int& n)
Also: where is delete? Remember: mapping new to delete is bijection: every new corresponds to single delete placed somewhere in code.
First of all, did you learn how to use an pointer correctly ? because if you know how to use pointer u should know that when you declare a pointer you need to be initialized to NULL before you can use it, correct me if i'm wrong.
Example
int *b = nullptr;
int *b = NULL;
int *b = 0;
int *b(0);
It's all the same thing but in an different way
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 9 years ago.
This code takes value returned from a function, creates and puts it in a new address space called variable 'b'
int main()
{
int b;
b = topkek();
std::cout << &b;
};
int topkek()
{
int kek = 2;
return kek;
};
Now I understand because variable kek was inside of topkek method I can not access it from main() method. With C++ and pointers, I figured out how I could access a variable declared inside a method even after the method has terminated, look at this code.
int main()
{
int * a;
a = topkek(); //a is now pointing at kek
std::cout << *a; //outputs 2, the value of kek.
*a = 3;
std::cout << *a; //output 3, changed the value of kek.
std::cin >> *a;
};
int * topkek()
{
int kek = 2;
int* b = &kek; //intializing pointer b to point to kek's address in stack
return b; //returning pointer to kek
};
Is this method safe? Would the compiler prevent kek's address space being overwritten later in code because it still understand it's being used?
This is undefined behavior: once the function finishes, accessing a variable inside it by pointer or reference makes the program invalid, and may cause a crash.
It is perfectly valid, however, to access a variable when you go "back" on the stack:
void assign(int* ptr) {
*ptr = 1234;
}
int main() {
int kek = 5;
cout << kek << endl;
assign(&kek);
cout << kek << endl;
}
Note how assign has accessed the value of a local variable declared inside another function. This is legal, because main has not finished at the time the access has happened.
No it is not safe. After your function finished execution, you are not pointing to an int anymore but just to some random place in memory. Its value could be anything since it can be modified elsewhere in your program.
Most definitely not safe. Undefined behavior will result.
When a local variable is "created", the compiler does so by giving the variable some space on the the stack [1]. This space is available for the variable as long as you are inside that function. When the function returns, the space is released, and available for other functions to use. So the address of b in your second code is returning a pointer to memory that will be releasted just after the return finishes.
Try adding something like this:
int foo()
{
int x = 42;
cout << "x = " << x << endl;
return x;
}
and call foo after your call to topkek, and it's pretty certain that the value in kek (or pointed to by kek) will change.
[1] For the pedants: Yes, the C++ standard doesn't specify that there needs to be a stack, or how local variables are supposed to be used, etc, etc. But in general, in nearly all compilers available today, this is how it works.
This will be safe:
int * topkek()
{
static int kek = 2;
int* b = &kek; //intializing pointer b to point to kek's address in stack
return b; //returning pointer to kek
};
Locally allocated automatic types will be automatically deallocated when exiting the function scope. The pointer you return will then point to deallocated memory. Accessing this memory will result in undefined behaviour.
int* topkek() {
int kek = 2; // Create a local int kek
int* b = &kek; // Declare pointer to kek
return b; // Return pointer to local variable. <-- Never do this!
}; // kek is destroyed and the returned pointer points to deallocated memory.
This is undefined behavior. After returning from the function, kek does not exist any more, and the pointer returned points into nirvana, to the location where kek once was. Accessing it gives undefined behavior. Undefined behavior means, anything can happen. You could indeed get the value that once was in kek or your application crashes, or you get some garbage value, or your compiler sees fit to order you a pizza online, with extra cheese, please.
This is undefined behavior, kek is a local variable and the memory it resides in will be released once you exit topkek. It may seem like it works but since it is undefined anything can result, it can break at any time and you can not rely on the results.
First, this is definitely unsafe as others have noted. But based on your usage, I think you might actually be trying to define an object. For example, this code might be what you want:
struct topkek{
int kek;
int *operator()() {
kek = 2;
return &kek;
}
};
int main()
{
topkek mykek;
int *a = mykek(); // sets mykek.kek to 2, returns pointer to kek
std::cout << *a;
*a = 3;
std::cout << *a;
std::cin >> *a;
};
This will give you clean access to the underlying kek variable in a totally safe way. You can of course put any code you want into the operator() method.
I am doing a procedure and it's working but I'm not sure if it'll work in all cases as it's not conventional.
void func (int &num){
num=blah;
}
int main() {
int num;
func(num);
}
I know the conventional way of doing this is as below but still I have a lot of code in the previous format I prefer not to change as it works just fine. What I don't understand is whether I'm just being lucky.
void func (int* num){
*num=blah;
}
int main() {
int num;
func(&num);
}
In fact there is a bit more complicated version of it as well:
void func(float* &list){
list=new float[3];
}
int main() {
float *list;
func(list);
}
which again I understand the conventional way of doing it is as below.
void func(float** list){
*list=new float[3];
}
int main(){
float *list;
func(&list);
}
Your help is much appreciated as I'm in total confusion.
Your first example is correct - you're passing an int by reference to func().
Your second example also fine (now that you've edited it). In this case, you're passing an int * by value to func().
Your third and fourth examples are also both correct. In the third, you're passing a float * by reference. In the second case, you're passing a float ** by value (which is semantically similar to passing a float * by reference, which might be why you're confusing them).
There's nothing "conventional" or "unconventional" about any of your example code. All of it is 100% correct and will work fine. Though there are some subtle semantic differences between passing pointers by value and passing by references, these examples are ok.
The syntax with int & is not C, but C++. It is a so-called reference. If your C (not C++) compiler accepts is, then it is a non-standard extension (for a C++ compiler it's part of the language, of course).
The basic mechanics of a reference is that it acts as a name (or another name) for an existing object. For example:
int a;
int& b = a;
b = 3; /* equivalent to a = 3 */
One way to think about the reference is as an automatically dereferenced pointer (that's also how it is commonly implemented). That is, the above code is equivalent to
int a;
int* pb = &a;
*pb = 3;
The Form Func(int &x) is the c++ form of pass by reference c does not support this. It is logically equivocation of passing by a pointer. The comnplier take the address for you implicitly in the call.
In C you would allways declare
Func(int *x)
{ ... }
And call it
Func(&SomeInt);