Is there any difference between new char[n] and new (char[n])?
I have the second case in a generated code, g++ (4.8.0) gives me
ISO C++ does not support variable-length array types [-Wvla]
This makes me think if these two are the same or not.
new char[n] means "allocate n objects of type char.
does new (char[n]) mean "allocate 1 object of type array of n chars"?
deleting the first is clear.
should I delete the second with delete or delete[]?
are there any other differences I should be aware of?
may I safely remove the parentheses and turn the second case into the first, when other parts of the software expect the second?
The code is generated by a third party software (and used by other parts of the software), so I cannot just "use vector instead".
This is minimal example:
int main (void)
{
int n(10);
int *arr = new (int[n]); // removing parentheses fixes warning
*arr = 0; // no "unused variable" warning
return 0;
}
The basic issue here is that C++ does not allow an array bound [n] to be used in a type unless n is a constant expression. g++ and some other compilers will sometimes allow it anyway, but it's impossible to get consistent behavior when you start mixing variable-length-arrays and templates.
The apparent exception int* p = new int[n]; works because here the [n] is syntactically part of the new expression, not part of the type provided to the new, and new does "know how" to create arrays with length determined at runtime.
// can be "constexpr" in C++11:
const int C = 12;
int main() {
int* p1 = new int[C];
int* p2 = new (int[C]);
typedef int arrtype[C];
int* p3 = new arrtype;
int n = 10;
int* p4 = new int[n];
// int* p5 = new (int[n]); // Illegal!
// typedef int arrtype2[n]; // Illegal!
// int* p6 = new arrtype2;
delete[] p1;
delete[] p2;
delete[] p3;
delete[] p4;
}
Semantically, though, after any final [C] is used to convert a type into an array type, the new expression only cares about whether it's dealing with an array or not. All the requirements about type of the expression, whether to use new[] and delete[], and so on say things like "when the allocated type is an array", not "when the array new syntax is used". So in the example above, the initializations of p1, p2, and p3 are all equivalent, and in all cases delete[] is the correct deallocation form.
The initialization of p4 is valid, but the code for p5 and p6 is not correct C++. g++ would allow them anyway when not using -pedantic, and by analogy I'd expect the initializations for p4, p5, and p6 to also all be equivalent. #MM's disassembly supports that conclusion.
So yes, it should be a safe improvement to remove the "extra" parentheses from this sort of expression. And the correct deletion is the delete[] type.
new T[N] makes an array of N elements of type T.
new (T[N]) makes a single object of type T[N].
The effect is the same (and both expressions yield a T * that points to the first element of the array and needs to be deleted with delete[] (cf. 5.3.4/5), but clearly T[N] must be a valid type in the latter case, so N must be a constant expression, while in the former case it is a dynamic argument of the array-new expression.
new int [n]
//Allocates memory for `n` x `sizeof(int)` and returns
//the pointer which points to the beginning of it.
+-----+-----+-----+-----+-----+-----+-----+-----+------+------+
| | | | | | | | | | |
| | | | | | | | | | |
| | | | | | | | | | |
+-----+-----+-----+-----+-----+-----+-----+-----+------+------+
new (int [n])
//Allocate a (int[n]), a square which its item is an array
+----------------------------------------------------------------+
|+-----+-----+-----+-----+-----+-----+-----+-----+------+------+ |
|| | | | | | | | | | | |
|| | | | | | | | | | | |
|| | | | | | | | | | | |
|+-----+-----+-----+-----+-----+-----+-----+-----+------+------+ |
+----------------------------------------------------------------+
In fact both of them are equal.
Here is the code generated by assembler (just an ignorable difference):
int n = 10;
int *i = new (int[n]);
int *j = new int[n];
i[1] = 123;
j[1] = 123;
----------------------------------
! int *i = new (int[n]);
main()+22: mov 0x1c(%esp),%eax
main()+26: sub $0x1,%eax
main()+29: add $0x1,%eax
main()+32: shl $0x2,%eax
main()+35: mov %eax,(%esp)
main()+38: call 0x401620 <_Znaj> // void* operator new[](unsigned int);
main()+43: mov %eax,0x18(%esp)
! int *j = new int[n];
main()+47: mov 0x1c(%esp),%eax
main()+51: shl $0x2,%eax
main()+54: mov %eax,(%esp)
main()+57: call 0x401620 <_Znaj> // void* operator new[](unsigned int);
main()+62: mov %eax,0x14(%esp)
!
! i[1] = 123;
main()+66: mov 0x18(%esp),%eax
main()+70: add $0x4,%eax
main()+73: movl $0x7b,(%eax)
! j[1] = 123;
main()+79: mov 0x14(%esp),%eax
main()+83: add $0x4,%eax
main()+86: movl $0x7b,(%eax)
You must delete both of them by delete [] ...
Related
I've been reading the book "Jumping into C++", and am currently reading up on pointers. This is an exercise from the book:
"What are the final values in x, p_int, and p_p_int in the following code:
int x = 0;
int *p_int = & x;
int **p_p_int = & p_int;
*p_int = 12;
**p_p_int = 25;
p_int = 12;
*p_p_int = 3;
p_p_int = 27;
And I get the error:
"Assigning to int * from incompatible type int"
On the last three lines.
I don't know why this is happening, and would appreciate any insight.
Furthermore, assuming that this code somehow works, I would think that since all pointers are just pointing towards a single memory (**p_p_int -> *p_int -> x), the last value assignment would dictate the final value of the memory location. However in the book, the answer is:
x = 25, p_p_int = 27, p_int = 3
Is this correct? If so, could anyone explain this to me?
As you can see p_int has as static type int *, and on the last three line you are doing something like
p_int = 12;
where 12 is an int, and so can't be assigned to a pointer (same thing to the other 2 lines)
However, x p_int p_p_int have different values because x contains the integer value, p_int the address of x and p_p_int the address of p_int.
Also keep in mind that this is a """"compilable"""" C code, not C++, but you will get 3 warnings also on C compiler telling you that you are assigning to a pointer an incompatible type
This part:
p_int = 12;
*p_p_int = 3;
p_p_int = 27;
There is no way this compiles with any confirming C++ compiler. It is just ill-formed. Even if you used casts to make it work, you'd cause undefined behavior. Try a different book.
int *p_int = & x;
int **p_p_int = & p_int;
These lines all point to the same memory in location (variable x).
There are three variables in your code snippet. Here is a table showing the value each variable would have after the execution of each of the lines (if the code were to actually compile).
| x | p_int | p_p_int |
-------------------------+----+-------+---------|
int x = 0; | 0 | undef | undef |
int *p_int = & x; | 0 | &x | undef |
int **p_p_int = & p_int; | 0 | &x | &p_int | <-- begin: all variables lead to x
-------------------------+----+-------+---------|
*p_int = 12; | 12 | &x | &p_int |
**p_p_int = 25; | 25 | &x | &p_int |
-------------------------+----+-------+---------| <-- end: all variables lead to x
p_int = 12; | 25 | 12 | &p_int | <-- p_int now points to garbage
*p_p_int = 3; | 25 | 3 | &p_int |
-------------------------+----+-------+---------|
p_p_int = 27; | 25 | 3 | 27 | <-- p_p_int now points to garbage
------------------------------------------------/
I've used undef to indicate that the variable does not yet exist (i.e. is undefined); &x and &p_int to represent the addresses of those variables (since an exact value is not knowable).
This is a thought exercise to see if you understand different levels of indirection, if you realize that *p_int and p_int refer to different values in memory. As you noticed, it does not compile. Assigning a numeric literal to a pointer is almost certainly an error, of no use outside this sort of thought experiment. In real code, a line like p_int = 12 is probably a typo (likely intended to be *p_int = 12) and the compiler will alert you to this.
Fortunately, the author seems to be aware of the inadvisability of trying to access the memory at addresses 12, 3, and 27, as neither p_int nor p_p_int was de-referenced while storing a bogus address. Still, it would be nice if the author acknowledged these limitations, or better yet devised an exercise that does not need such a disclaimer. (Hopefully this was an isolated slip. Unlike some people, I would not denounce an entire book on the basis of a single exercise. Books are long, C++ is complex, and mistakes happen. )
What will be the output of following c++ code snippet.
How we can assign a value to a variable which occupies no memory (0 bytes).Also doing pointer arithmetic gives false results(implied)
int main()
{
int arr[0];
arr[1]=1;
cout<<arr[1]<<endl;
cout<<sizeof(arr)<<endl;
int *p=arr;
int *q=p+1;
cout<<p-q;
return 0;
}
Sample execution ==> https://code.hackerearth.com/f8d7b1G
Well, actually, your code causes undefined behaviour.
Let's see how it works.
int a, b;
int c[2];
This will look like (imagine this as a stack inside the function "main"):
/***
+--------------------+ <- 0xXXXXXXXX (initial address)
| a |
+--------------------+ <- 0xXXXXXXXX + sizeof int (initial address + size of variable a) == &a
| b |
+--------------------+ <- ... + sizeof int (... + size of variable b) == &b
| c[1] |
+--------------------+
| c[0] |
+--------------------+ <- ... + number of bytes that are being allocated by the array (it's the pointer to the array)
== c or &c[0]
+--------------------+
| c (pointer) |
+--------------------+
// remember that compiler don't have to allocate it like this, it's just an example
***/
When you are trying to do something like this:
c[0] = 1;
it's being the same as:
*(c + 0) = 1;
because variable "c" contains the pointer to the array. It also explains why does a compiler allocate it reversely on the stack (because if we want to access a specific member of an array, we have to write something i did a little bit upper — *(c + N) = 1;, because STACK GROWS DOWN. If you still confused with it, write it in the comments below, i'll explain.
So, if you write something like this
int a, b;
int c[0];
It looks like:
/***
+--------------------+ <- 0xXXXXXXXX (initial address)
| a |
+--------------------+ <- 0xXXXXXXXX + sizeof int (initial address + size of variable a) == &a
| b |
+--------------------+ <- ... + sizeof int AND
+ number of bytes that are being allocated by the
array.
When the number of bytes is ZERO,
it equals to the address of the variable "b",
because &b + 0 == &b
+--------------------+
| c (pointer) |
+--------------------+
***/
So, we could say that what you are doing is:
*(&b + 1) = 1;
THIS IS VERY UNSAFE. Imagine there was no variable "b" or variable "a", you would just be managing something you shouldn't.
That's why zero-sized arrays are not allowed in C++ standart.
char *t=new char();
and
char *t=new char[102];
as my code was accepted by using the latter one?
//BISHOPS SPOJ
char *t=new char();
Allocates memory for a single character, and calls the default constructor.
char *t=new char[102];
Creates an array of 102 chars and calls the default constructor.
As the default constructor for POD types is nothing, the difference is the amount of memory allocated (single char vs array of char)
Actually both are pointers on char, but second is pointer to char array.
Which allows you to store 102 characters into the array.
char *t=new char[102];
0 1 2 3 101
+---+---+---+---+ ... +---+
| | | | | |
+---+---+---+---+ ... +---+
^
|
-----------------------------+---+
| * |
+---+
t
It allows you to dereference these indexes 0-101.
While first one allows you to store only one character.
char *t=new char();
0
+---+
| |
+---+
^
|
-----------------------------+---+
| * |
+---+
t
Where dereferencing other index than 0 would lead to access outside of bounds and undefined behavior.
Deleting
To delete an character char *t=new char();
delete t;
Where to delete an array char *t=new char[102]; you have to write empty brackes, to explicitly say its an array.
delete [] t;
Same with these codes
char *t = new char[10]; // Poitner to array of 10 characters
char *t = new char(10); // Pointer to one character with value of 10
Memory initialialization
char *t = new char(); // default initialized (ie nothing happens)
char *t = new char(10); // zero initialized (ie set to 0)
Arrays:
char *t = new char[10]; // default initialized (ie nothing happens)
char *t = new char[10](); // zero initialized (ie all elements set to 0)
I read this C++ tutorial, and in the pointers section there is a confusing example, exactly this:
double (*pVal2)[2]= new double[2][2]; //this will add 2x2 memory blocks to type double pointer
*(*(pVal2+0)+0) = 10;
*(*(pVal2+0)+1) = 10;
*(*(pVal2+0)+2) = 10;
*(*(pVal2+0)+3) = 10;
*(*(pVal2+0)+4) = 10;
*(*(pVal2+1)+0) = 10;
*(*(pVal2+1)+1) = 10;
*(*(pVal2+1)+2) = 10;
*(*(pVal2+1)+3) = 10;
*(*(pVal2+1)+4) = 10;
Is int (*pVal)[2] an array pointer?
I do not understand why is it allocating memory for double[2][2] but the *(*pVal2+1)+4) goes to 4?
Using the spiral rule:
+--------+
| +---+ |
| ^ | |
double (*pVal2)[2];
^ ^ | |
| +-----+ |
+---------------+
pVal2 is a pointer to an array of 2 doubles. Or, simpler:
using T = double[2];
T *pVal2 = new T[2];
The rest of the code leads to undefined behavior as: *(p + idx) is equivalent to p[idx], so *(*(pVal2+1)+4) is equivalent to pVal2[1][4].But the type of pVal2[1] is double[2], so there is no 5th element there...
What is the difference between doing this:
int i = 5, j = 6, k = 7;
int *ip1 = &i, *ip2 = &j;
int *ipp = ip1;
and doing this:
int **ipp2 = &ip1;
Don't they do the same thing? hold a pointer(ip1) which points to a variable, i?
ipp2 points to ip1. This is entirely different from pointing to i.
Sample code:
int *ip1 = &i;
int **ipp2 = &ip1;
printf("%d\n", **ipp2); // 5
ip1 = &j;
printf("%d\n", **ipp2); // 6
All the variables have a location in memory where their values are held. Let's explore the relationships between the values of i, ip1, ipp, and ipp2
This is what you get when the statement i = 5; is executed. i has its location in memory and the value at location is set to 5.
i -> +--------+
| 5 |
+--------+
^
|
A1 (address of i)
This is what you get when the statement int* ip1 = &i; is executed. ip1 has its location in memory and the value at that location is set to the address of i, which we designate as A1.
ip1 -> +--------+
| A1 |
+--------+
^
|
A2 (address of ip1)
This is what happens when you execute the statement int* ipp = ip1;. The value at the memory location of ipp is set to the value of ip1, which is A1.
ipp -> +--------+
| A1 |
+--------+
^
|
A3 (address of ipp)
This is what happens when you execute the statement int** ipp2 = &ipp;. The value at the memory location of ipp2 is set to A3, which is the address of `ip1.
ipp2 -> +--------+
| A3 |
+--------+
^
|
A4 (address of ipp2)
How does dereferencing work:
*ip1 = *A1 = 5
*ipp = *A1 = 5
*ipp2 = *A3 = A1
**ipp2 = **A3 = *A1 = 5
Pointers are often used to change the value of a variable inside a function:
void incr(int *ip) { *ip++; }
void f() { int i = 0; incr(&i); printf("%d\n", i); // 1
Now it's not any different with a pointer to a pointer. You can pass the pointer to a pointer to a function, and that function can change what that pointer points to: the original pointer!
char *mom = "mom";
char *pop = "pop";
chooseMomOrPop(int choosePop, char **momOrPop) { *momOrPop = choosePop ? pop : mom; }
void f() { char *mp = mom; chooseMomOrPop(1, &mom); printf("%s\n", mom); } // pop
Very simple: a pointer is an address where a variable stays in memory. Since a pointer is itself a variable, its address could be stored in another pointer, and so on. To better have in mind how a pointer is and how it works, just think it is an address. The type of the pointer, ie int in int * refers to the type of the data pointed, and effect how the pointer "react" to addition or subtraction, as described in pointer arithmetic. A 'pointer to pointer of int' is an int**, so is always an address pointing to an int*, and when incremented it will move the address to as many byte as necessary to point the next int*