This question already has answers here:
Can initializing expression use the variable itself?
(3 answers)
What's the behavior of an uninitialized variable used as its own initializer?
(3 answers)
Self-assignment of variable in its definition
(3 answers)
Closed 6 months ago.
I am learning C++ using the books listed here. In particular, I read that using an uninitialized local variable of built in type is undefined behavior. Now, I came across the below given example where the user seems to be using uninitialized variables x and y. The user says:
#include <string>
template<typename T>
T num_convert(const char* s, const T) {
return static_cast<T>(std::stoll(s));
}
int main() {
//--------------------------v---------------> is this UB because x is uninitialized?
int x = num_convert("55", x);
//-----------------------------------v------> is this UB because y is uninitialized?
long y = num_convert("5555555555", y);
}
In the above example, I've used arrows to highlight the points where I have doubts. In particular, I want to know that are the above two highlighted statements UB because x and y are not initialized and the user is passing those to the function by value?
I want to know that are the above two highlighted statements UB because x and y are not initialized and the user is passing those to the function by value?
Yes, your understanding is correct. The variable x and y are uninitialized local variables and they're being used/passed by value when calling the functions. Thus, the program has undefined behavior as x and y have indeterminate values and you're using/copying those values to the parameter of the function.
This question already has answers here:
Is there any way to find the address of a reference?
(10 answers)
Closed 2 years ago.
I am working with pointers and reference variable in C++.
int i=43;
int &refi=i;
What I know is the variable refi is bound to variable i. However it does not have its own memory. It is just a another name to the variable i. Then how can a pointer point to such unstored variable.
#include<iostream>
int main(){
int i=43;
int &refi=i;
int *p=&refi;
std::cout<<p;
return 0;
}
However I am not getting any error for the above code. Instead I am getting address of it.Am I wrong with the concept of reference variable here?If yes how?
The output is
0x61ff04
The reference has the same address in memory as the variable it's referencing. That essentially makes it an alias. Thus, when you take the address of a reference, you get the address of the original variable.
When I do the following:
1. int y = 5;
2. int &a = y;
3. cout << &a << endl; // the address of a is the same address of y
4. cout << a << endl; // this has the value of y, which is 5.
Why does the a has the same address of y? I know that changing a will change y also.
But how do you read line 2? Do you read it as address of a contains the value of y?
Does this mean that a and y share the same physically memory location? Or are there 2 different memory locations with the same address?
In line 2, you are creating a C++ reference, not using the address of operator. The reference causes a to be roughly equivalent to y for all uses including taking its address.
Effectively the symbol a is just another name for y.
References are (broadly) just syntactic sugar for pointers, so a is really just a pointer to y wrapped up with automatic dereferencing. (There is slightly more to it than that, but for the sake of discussion we can think of it that way without getting misled about anything.) So when you ask for the address of a, you are really asking for the underlying pointer value, which has been set to be &y.
When you ask for the value of a, it automatically dereferences the pointer, so it is giving you the value which is at &y. Naturally, this value has y's value.
Does this mean that a and y share the same physically memory location?
No, there are two different memory locations. One holds an int value, the other holds a pointer to that int value.
Or are there 2 different memory locations with the same address?
Pretty much, yes. y is not holding a pointer/address value, though; it is actually holding the integer value itself. (Remember that y is stack memory, not a pointer to a heap object.)
When you take the address of a reference, you are not getting back "a pointer to that reference". You will simply get back the address of the referent itself.
Read this:
http://www.tutorialspoint.com/cplusplus/cpp_pointer_operators.htm
int &a = y;
Here in line 2, you are declaring that "Address of 'a' is equal to the address of variable 'y' ".In other words, 'y' has another name 'a'.
cout << &a << endl; // the address of a is the same address of y
I think there cannot be two memory locations with same address.
It's just that two variables refer to the same address.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ Reference, change the refered variable
I know that references in c++ are just pointers that get dereferenced for you when you use them. This question is about how to access the underlying pointer and change it.
Consider this code:
int x;
int& x_ref = x; //now equivalent to x
int* x_ptr = &x; //stores address of x
int* x_ref_ptr = &x_ref; //ALSO stores address of x
int&* x_ref_ptr_ref = ???; //what would this mean?
I'm trying to change where a reference points after initialization. I have no concern for type safety or proper practices. Does the c++ language have any tool to let me accomplish this?
There is no pointer to reference, it's ill-formed. A reference is an alias to an object. How would a pointer to an alias work?
Also, it's a feature of the language that a reference can't be reseated. A reseatable reference is a pointer.
This is not possible by design. By using a reference instead of a pointer, you decide to never change its target after declaration, with all entailing drawbacks and advantages (one of which is its "automatic dereferencing". Read the Wikipedia entry on references carefully.
You will need to switch to pointers.
As background, I gave an answer to this post a little while ago:
Return array in a function
And it unintentionally kicked off a really long comment chain about pointers vs. arrays in C++ because I tried to oversimplify and I made the statement "arrays are pointers". Though my final answer sounds pretty decent, it was only after some heavy editing in response to a lot of the comments I got.
This question is not meant to be troll bait, I understand that a pointer and an array are not the same thing, but some of the available syntax in the C++ language certainly makes them behave very similarly in a lot of cases. (FYI, my compiler is i686-apple-darwin9-g++-4.0.1 on OS X 10.5.8)
For instance, this code compiles and runs just fine for me (I realize x[8] is a potential segmentation fault):
//this is just a simple pointer
int *x = new int;
cout << x << " " << (*x) << " " << x[8] << endl; //might segfault
//this is a dynamic array
int* y = new int[10];
cout << y << " " << (*y) << " " << y[8] << endl;
//this is a static array
int z[10];
cout << z << " " << (*z) << " " << z[8] << endl;
That particular snippet makes it look like pointers and arrays can be used almost identically, but if I add this to the bottom of that code, the last two lines won't compile:
x = y;
x = z;
y = x;
y = z;
//z = x; //won't compile
//z = y; //won't compile
So clearly the compiler at least understands that z and x are different things, but I can interchange x and y just fine.
This is further confusing when you look at passing arrays to functions and returning arrays from functions. Consider this example (again, I am aware of the potential segmentation faults here when passing x):
void foo(int in[])
{
cout << in[8] << endl;
}
void bar(int* in)
{
cout << in[8] << endl;
}
int main()
{
//this is just a simple pointer
int *x = new int;
foo(x);
bar(x);
//this is a dynamic array
int* y = new int[10];
foo(y);
bar(y);
//this is a static array
int z[10];
foo(z);
bar(z);
}
All this code properly compiles and runs on my machine.
I feel like I have a decent internal understanding of what's going on here, but if you asked me to articulate exactly what's happening, I don't feel like I could satisfactorily explain. So here's what I'm getting at:
When I pass an array to a function as int* in instead of int in[], what am I gaining or losing? Is the same true when returning an array as int*? Are there ever bad side effects from doing this?
If I asked you what the data type of y is, would you say pointer to int, array of ints or something else?
Similarly, what happens when I say x = y vs. x = z? I'm still able to use x[] and access the things that were originally in y or z, but is this really just because pointer arithmetic happens to land me in memory space that is still valid?
I've dug through all the similar array/pointer questions on SO and I'm having trouble finding the definitive explanation that clears this up for me once and for all.
C++ is statically typed, so of course the compiler understands that x and z are not the same kind of thing. They have different types - z is an array, x and y are pointers.
The reason z = x doesn't compile isn't (just) that the types are incompatible, though, it's that you can't assign to an array variable at all. Ever. x = z assigns to x, a pointer to the first element of z. x = y assigns the value of y to x.[*]
When I pass an array to a function as int* in instead of int in[], what am I gaining or losing?
They do exactly the same thing, so you have no choice to make. Possibly you have been misled by the fact that C++ syntax permits int in[] as a function parameter. The type of the parameter in is not any kind of array, it is int*.
If I asked you what the data type of y is
It's int*. That's what it's declared as, so that's what it is.
The value that it holds is a pointer to (the first element of) an array. I frequently use that formula: "pointer to (the first element of)" in cases where I'd like to say "pointer to array", but can't because there's the potential for ambiguity as to whether the type involved is pointer-to-array, or not.
However, pointers-to-arrays are rarely used in C++, because the size of the array is part of the type. There's no such type as "pointer to an array of int" in C++, just "pointer to array of 1 int", "pointer to array of 2 int", etc. This usually isn't very convenient, hence the use of a pointer to the first element of an array whose size may not be known at compile time.
is this really just because pointer arithmetic happens to land me in memory space that is still valid
Pretty much, yes. The size of the array is part of the type of z, but is not part of the type of x or y, and also is not part of the type of the result of z decaying to a pointer to its first element. So y could be a pointer to the first of 10 elements, or just to 1 element. You only know the difference by context, and by requiring of your callers that the value you have points to what it's supposed to point to.
"Happens" is leaving too much to chance, though - part of your job when using arrays is to make sure you don't stray beyond their bounds.
[*] z = x isn't allowed, even after you've done x = z, because z is (and always will be) an particular array of 10 ints in memory. Back when C was designed, there was a question of whether array variables could in principle be "reseatable", meaning that you could do:
int z[10];
int y[10];
z = y; // z is now an alias for y
y[0] = 3;
// z[0] now has the value 3
Dennis Ritchie decided not to allow this, because it would prevent him from distinguishing arrays from pointers in a way that he needed to do. So z cannot ever refer to a different array from the one it was declared as. Read all about it here: http://cm.bell-labs.com/cm/cs/who/dmr/chist.html, under "Embryonic C".
Another plausible meaning for z = y could be memcpy(z,y,sizeof(z)). It wasn't given that meaning either.
The fundamental difference between a pointer and an array is that the pointer has a unique memory address that holds the address of the array data.
An array name, though treated as a pointer based on context, does not itself have a memory location whose address you can take. When it is treated as a pointer, its value is generated at runtime as the address of its first element.
That is why you can assign its value to another pointer but not vice versa. There is no pointer memory location to treat as an l-value.
Arrays are not pointers, but arrays easily decay to pointers to their first element. Additionally, C (and thus C++) allow array access syntax to be used for pointers.
When I pass an array to a function as int* in instead of int in[], what am I gaining or losing? Is the same true when returning an array as int*? Are there ever bad side effects from doing this?
You're gaining nothing, because int[] is just another way to write int*. If you want to pass an array, you have to pass it per reference, exactly matching its size. Non-type template arguments can ease the problem with the exact size:
template< std:::size_t N >
void f(int (&arr)[N])
{
...
}
If I asked you what the data type of y is, would you say pointer to int, array of ints or something else?
It's a pointer to the first element of a dynamically allocated array.
Similarly, what happens when I say x = y vs. x = z?
You assign the addresses of different objects of different types to the same pointer. (And you leak an int on the heap. :))
I'm still able to use x[] and access the things that were originally in y or z, but is this really just because pointer arithmetic happens to land me in memory space that is still valid?
Yep. As I said, pointers conveniently and confusingly allow array syntax to be applied to them. However, that still doesn't make a pointer an array.
Here's an snippet from this book (and C++ semantics follows from its backward compatibility with C). Array "are" pointers in the following cases:
An array name in an expression (in contrast with a declaration) is treated by the compiler as a pointer to the first element of the array (this does not apply to sizeof) (ANSI C Standard, 6.2.2.1)
A subscript is always equivalent to an offset from a pointer (6.3.2.1)
An array name in the declaration of a function parameter is treated by the compiler as a pointer to the first element of the array (6.7.1)
This basically means that:
int arr[20]; int* p = arr;
is equivalent to:
int arr[20]; int* p = &arr[0];
Then
int arr[20]; int x = arr[10];
is equivalent to:
int arr[20]; int x = *( arr + 10 );
And
void func( int arr[] );
is equivalent to:
void func( int* arr );
On the other hand, pointers are never transformed back into arrays - that's why your last two lines do not compile.
When I pass an array to a function as
int* in instead of int in[], what am I
gaining or losing? Is the same true
when returning an array as int*? Are
there ever bad side effects from doing
this?
AFAIK, one is just syntactic sugar for the other and they mean exactly the same.
The version with [] probably just gives a strong hint that this function expects a pointer into an array, not a pointer to a single object.
You will notice a difference when it comes to real multi-dimensional arrays vs array of pointers (to arrays), because in such case only the first dimension decays to a pointer with multi-dimensional arrays. Those things have a completely different layout in memory (one big contiguous block vs one small block of pointers to distinct blocks of memory).
If I asked you what the data type of y
is, would you say pointer to int,
array of ints or something else?
The type of y is a pointer to int. In fact, in case of a dynamically allocated array, you never get to see the array at all! That is, there is no way to determine the size of the allocation with sizeof, unlike actual arrays.
Similarly, what happens when I say x =
y vs. x = z? I'm still able to use x[]
and access the things that were
originally in y or z, but is this
really just because pointer arithmetic
happens to land me in memory space
that is still valid?
This is because x is a pointer. You will not be able to do z = x; because you can't assign to arrays.
There's no difference (at all) between a function parameter like int *in and int in[]. For a function parameter, these are just different ways of spelling pointer to T. The only way they can differ at all is (possibly) something like readability (e.g., if you intend to always pass the base address of an array, you might find array notation more fitting, whereas if you intend to pass the address of a single object, you might find pointer notation more tasteful).
In the code above, y clearly has the type pointer to int.
x and y are pointers, which can be assigned. z is an array, which cannot be assigned.
As an aside (which has some relevance to the topic - would have added this as a comment but don't have enough rep.) - you can gauge the number of elements in an array vs. using a pointer. Or stated differently sizeof returns sizeof(array_type)*num_elements_in_array vs returning the size of the pointer. Glib provides this macro for this purpose.
When I pass an array to a function as int* in instead of int in[], what am I gaining or losing? Is the same true when returning an array as int*? Are there ever bad side effects from doing this?
Your not gaining or losing anything
If I asked you what the data type of y is, would you say pointer to int, array of ints or something else?
I would call y a pointer to an array of ints
Similarly, what happens when I say x = y vs. x = z? I'm still able to use x[] and access the things that were originally in y or z, but is this really just because pointer arithmetic happens to land me in memory space that is still valid?
x = y does not make a copy of the array pointed to by y only a copy of the pointer in y.
x = z does not make a copy of the array z, only a pointer to the value of the first element.
Also, free allocated memory.