2

I don't understand why Delphi doesn't work like C++

float *buffer;
buffer=new float[2];
buffer[0]=0.1;
buffer[1]=0.2;
buffer+=1;
//now buffer[0] has value of buffer[1] and buffer[1] has value 0

Delphi code:

buffer: array of Single;
SetLength(buffer,2);
buffer[0]:=0.1;
buffer[1]:=0.2;
buffer:=buffer+1; //doesn't work
28
  • 1
    @CaptainObvlious If you don't want to help, please don't spam. Commented Apr 22, 2014 at 19:39
  • 5
    Please ask a question. Please also show what you have tried so that we have some idea where to pitch an answer. Please give the context of the code. Translating it literally is easy but likely to be misleading and unhelpful. Commented Apr 22, 2014 at 19:40
  • 2
    Stack Overflow, like most free help websites, has rules and guidelines for how to ask a question and what types of questions to ask. Please review the FAQ to have a better understanding why people are hesitant to help you. Long story short, you're expected to put in the effort and when you get stuck, ask us specific questions. We can answer your question, but without knowing more about what this code is actually used for, I doubt any answer would be really useful. Besides, how can anyone expect to learn if they always have other people do their research and work? Commented Apr 22, 2014 at 20:00
  • 6
    @user3560787 This is a question and answer site. Not a convert my code for me site. I also don't believe you're 10 years old even though you act like you are. Commented Apr 22, 2014 at 20:05
  • 4
    Your latest edit makes this a better question. +1. You got upset at the comments, but that was because the original question was not good enough. I suggest you reflect on this experience, and the similar one with your earlier, now deleted question. In future you will have better results if you think a bit more before asking, and spend a bit more time explaining the question. One final word of advice. Don't ever say "doesn't work". Always explain what you expect to happen, and what actually does happen. Commented Apr 22, 2014 at 20:43

2 Answers 2

8

The Delphi code you showed is not an equivalent translation to what the C++ code is doing - utilizing pointer arithmetic. The following would be a closer translation:

If you are using D2009+:

{$POINTERMATH ON}

var
  buffer: PSingle;

GetMem(buffer, SizeOf(Single) * 2);
buffer[0] := 0.1;
buffer[1] := 0.2;
buffer := buffer + 1;

If you are using D2007 or earlier, use something more like this instead:

type
  TSingleArray = packed array[0..(MaxInt div SizeOf(Single))-1] of Single;
  PSingleArray = ^TSingleArray;

var
  buffer: PSingle;

GetMem(buffer, SizeOf(Single) * 2);
PSingleArray(buffer)^[0] := 0.1;
PSingleArray(buffer)^[1] := 0.2;
Inc(buffer);
Sign up to request clarification or add additional context in comments.

6 Comments

Your code does exactly what C++ does. +1 for you. And thank you very much, sir! :)
Can you modify the code to prevent memory leak? I've already put FreeMem in finally block, but it seems that there is memory leak.
The C++ code leaks too. What is the context of this code.
@DavidHeffernan: don't change the semantics of people's answers. I reverted your change. When POINTERMATH is on, buffer + 1 works, and that I how I wanted my answer to show.
@user3560787: If you want to not have memory leaks, don't code it this way. You will lose the reference to the original pointer if you change it. If you use a dynamic array, the compiler cleans it up for you. Sometimes, an exact translation isn't the best, when the other language offers a better facility.
|
7

A lot of the comments you're getting are happening because your C++ code is nonsensical, and people don't understand why you would want to do that, in C++ or Delphi.

A pointer points to a memory address, which is generally assumed to contain a variable. But in C (and C++ and similar languages) a pointer is also used as an array; instead of a well-defined "array type", you simply have a pointer to the first element and array syntax that works with it. Your buffer+=1 line basically means "move the pointer to the variable element after the one it's currently at." You claim that now buffer[0] has value of buffer[1] and buffer[1] has value 0, but it's not quite that simple. The old buffer[0] didn't go anywhere; you just moved the pointer.

You went from:

  | 
  V
-----------------
| 0 | 1 | beyond|
-----------------
|0.1|0.2|???????|
-----------------

to:

      | 
      V
-----------------
| 0 | 1 | beyond|
-----------------
|0.1|0.2|???????|
-----------------

It now looks like buffer[0] has changed its value, but the values haven't changed; you just moved the pointer.

And I left the values after the end of the array marked as ?s for a reason. That's not really a 0; that's undefined, and it contains whatever happens to be in memory at those bytes. It could be a 0 now, but if you run it again (or run it on a different computer) you could easily get some random number. "Undefined behavior" is programmer-speak for "things go wrong in unpredictable and hard-to-track-down ways." It's not a good thing. C is full of it; Delphi, much less so.

The reason what you're trying to do doesn't work in Delphi is that Delphi has well-defined array types that are completely different from pointers. A dynamic array may look like "just an array" but it's actually a data structure containing metadata about the array, with an array glued on the end of it. So you can't move the pointer around; there is no "element pointer" the way there is with C code.

If you really want to get a pointer to an element in an array, perhaps because you're scanning the array one element at a time, you declare a variable of a pointer type (with the ^ operator) and set it with the @ operator, like so:

var
buffer: array of Single;
ptr: ^single;
begin
   SetLength(buffer,2);
   buffer[0]:=0.1;
   buffer[1]:=0.2;
   ptr := @buffer[1];
end;

But again, a pointer is not an array, an array is not a pointer. So you would not be able to say ptr[0]. (A few pointer types, such as PChar, make an exception to this rule for practicality reasons because they represent C API strings, but as a general rule you should not treat pointers like arrays.)

And if what you want to do is scan through an array, there's a better way. Because the array type is well defined and Delphi knows how long it is, you can do this:

for value in buffer do
   //do whatever

This is called an enumerator, and it acts as a special kind of for-loop that loops over each element in the array, feeding it into the index variable.

I hope this helps. If not, please clarify what you're trying to do with this code and I'll try and explain better. :)

24 Comments

@mason What forms of UB exist in C++ that do not in Delphi?
@David: Plenty of things. Relevant to this example: reading/writing beyond the bounds of an array. In C++ this causes undefined behavior. In Delphi it raises an exception.
But if coded properly in the first place, shouldn't make a difference in the end :-)
@JerryDodge: Yeah, but that's the whole point. To err is human. People don't code properly. Even really good developers who get almost everything right only get almost everything right. So the question is, what happens when you make a mistake? And this is where C fails miserably.
Indeed, one of the biggest problems I've seen in any language is unhandled exceptions forcefully ending the process - something which the VCL does quite well preventing.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.