-6

Can someone tell me what is the difference between these two lines of C++ code?

int *p = new int (7);

and

int *p = new int [7];

I can't spot any difference except that in the first one it put the number 7 in p[0] , Is there any other difference? And In the case when there will be char instead of int what will happen?

Thanks in advance.

Seyed Parsa Neshaei
  • 3,470
  • 18
  • 30

4 Answers4

4

One is an array of 7 items

new int [7]

The other is just initialising a pointer to an int with the value of 7

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
4
int *p = new int (7);

Looking at it piece by piece: int *p creates a pointer to an int. new int (7) creates a new int on the heap, and stores the value 7 there. The = tells the computer that p should point to the address of that newly created int.

int *p = new int [7];

Again, taking it piece by piece: We already know int *p creates a pointer to an int. new int [7] creates an array of ints. The array is size 7, so the computer sets aside memory space for 7 integers. The = in this case tells the pointer it should point to the start of the array, that is, it will point to the first of those ints.

When you use the square brackets [i] with a pointer, e.g. p[i] you're telling the computer to give you what is at the memory address pointed to by p but offset by i. When p points to the start of an array you can use p[i] to access different parts of the array. But if p points to a single int, p[i] makes no sense, so it is undefined. One possible outcome is that it will just offset the memory address and give you whatever happens to be stored in memory next to your int, but the behaviour is undefined so different compilers, computers, operating systems / whatever may result in different outcomes.

Verwirrt
  • 403
  • 2
  • 13
3

The first one only creates one int, not an array. Trying to access anything beyond it, e.g. p[1], is undefined behavior.

selalerer
  • 3,766
  • 2
  • 23
  • 33
  • 5
    @RazBenNetanel It´s true, but you don´t understand how a computer works. Sure there is memory after this one int, but it´s not yours, and anything can be there. – deviantfan Jul 05 '15 at 15:06
  • 2
    @RazBenNetanel Although it looks like you can, you actually cannot do that legally. Run your code through valgrind to see what's going on, or replace 7 with 7000000, and run a loop to see your program crash on almost any computer. – Sergey Kalinichenko Jul 05 '15 at 15:07
  • 1
    ***I can access p[i] there is value on 0 there.*** Undefined Behavior. – drescherjm Jul 05 '15 at 15:08
  • I do understand there is a memory there and I do know it is not mine , but as far as i know, i should get an run time error when i try to reach p[i] , shouldn't i? @deviantfan – Raz Ben Netanel Jul 05 '15 at 15:09
  • @RazBenNetanel I'll add to what was already commented that "undefined behavior" is an expression used in the C++ standard that says the implementer of the compiler doesn't have to output an error or do any special handling for this case but the implementer needs not commit to any certain behavior at run time for this case. – selalerer Jul 05 '15 at 15:10
  • This SO Q&A may help understand: http://stackoverflow.com/questions/1239938/c-accesses-an-array-out-of-bounds-gives-no-error-why – selalerer Jul 05 '15 at 15:12
  • 3
    @RazBenNetanel An modern OS separates memory into blocks of a certain size ("pages"), and every program/process gets some pages assigned. p[1] is likely to be in the same page as p[0], so it does belong to your program => The OS won´t throw any errors. But within your program, you´re accessing the values of other variables or code bytes, and this will lead to strange things (and this isn´t checked by anything, as long as it doesn´t leave the page) – deviantfan Jul 05 '15 at 15:13
  • 1
    @RazBenNetanel: _"as far as i know, i should get an run time error when i try to reach p[i] , shouldn't i?"_ No. – Lightness Races in Orbit Jul 05 '15 at 15:14
1

That's is not true sadly , I can access p[i] there is value on 0 there... – Raz Ben Netanel 29 mins ago

So here is your next experiment - but this is just a learning exercise! As usual, you should not try this at home.

int t213(void)
{
   // let me create an array of ints on the stack
   int  buff[128];
   // and initialize them to a distinctive patterh
   for (int i=0; i<128; i++) buff[i] = 0x55555555;

   void* place0 = buff; // offset 0 into buff

   // if you want, try printing buff[0] (and maybe 1 or 2 more) 
   // use hex to see the 55555555 pattern

   // next I use placement new to do something that makes everyone
   // (familiar with UB) uncomfortable ... Relax, I have an embedded 
   // software background and understand that the behavior we shall 
   // observe is not guaranteed, not even from 1 compile to the next

   int* p1 = new (place0) int(7);  // a single int, initialized to 7, 
   void* p1Addr = p1;              // at location place0

   // (no - I know your thinking about it, but don't do this.  
   // essentially because neither C nor C++ have memory layout symantics.)

   dtbAssert(p1Addr == place0)(p1Addr)(place0); // no assert occurs
                                                // both addresses are the same

   // test the soup
   std::cout << "\np1      : " << std::setw(12) << std::hex << *p1     << "  @" << DTB::hexComma(p1Addr)
             << "\nbuff[0] : " << std::setw(12) << std::hex << buff[0] << "  @" << DTB::hexComma(&buff[0])
             << "\nbuff[1] : " << std::setw(12) << std::hex << buff[1] << "  @" << DTB::hexComma(&buff[1])
             << std::endl;

   // now spoil the soup:
   p1[1] = 0xdeadbeef; // oops - UB   NO COMPILER WARNING

   // then test the soup once more
   std::cout << "\np1      : " << std::setw(12) << std::hex << *p1     << "  @" << DTB::hexComma(p1Addr)
             << "\nbuff[0] : " << std::setw(12) << std::hex << buff[0] << "  @" << DTB::hexComma(&buff[0])
             << "\nbuff[1] : " << std::setw(12) << std::hex << buff[1] << "  @" << DTB::hexComma(&buff[1])
             << std::endl;

   return(0);
}

And since I used some private tools, I will include the output:

p1      :            7  @7ffe,c3bb,3910
buff[0] :            7  @7ffe,c3bb,3910
buff[1] :     55555555  @7ffe,c3bb,3914

p1      :            7  @7ffe,c3bb,3910
buff[0] :            7  @7ffe,c3bb,3910
buff[1] :     deadbeef  @7ffe,c3bb,3914

Note the code line marked with the comment "// oops - UB ".

That line uses p1[1]. But the out-of-bound index is not noticed by the compiler - not even a warning.

Because it is UB, the compiler generated what-ever it wanted to. In this case (but not guaranteed), it is as if p1[1] exists -- note that buff[1] changes from 55555555 to deadbeef

Research term - degenerate pointer

2785528
  • 5,438
  • 2
  • 18
  • 20