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
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    @CaptainObvlious If you don't want to help, please don't spam. – user3560787 Apr 22 '14 at 19:39
  • @CaptainObvlious I'm just only 10 years old and learning programming. – user3560787 Apr 22 '14 at 19:40
  • 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. – David Heffernan Apr 22 '14 at 19:40
  • @DavidHeffernan Pleas convert my code to Delphi. All help will be appreciated. – user3560787 Apr 22 '14 at 19:41
  • 1
    No thank you. You need to do a little more than ask us to translate the code. – David Heffernan Apr 22 '14 at 19:42
  • I am helping you. You need to follow the advice in my first comment. Please do so with an edit to the question. We already went through this in your earlier question. We can totally help you but it is not possible until you start cooperating. – David Heffernan Apr 22 '14 at 19:45
  • Folks, from the OP's point of view: There is basically no way to provide code to this elementary subject: Allocate an array and get a pointer past the end of the array. –  Apr 22 '14 at 19:47
  • OP, try looking at this question and see if you can find something that will help you: http://stackoverflow.com/questions/7088005/conversion-of-pointers-and-arrays-from-c-to-delphi – Graymatter Apr 22 '14 at 19:48
  • Your edit doesn't really help. There's still no context. No explanation why you would allocate an array and then advance the pointer to it beyond the end. What are you trying to do. Please can you make some effort. – David Heffernan Apr 22 '14 at 19:50
  • @DavidHeffernan I'm learning Delphi, and I want to operate increasing pointer, I know Setlength function but it doesn't work like C++. – user3560787 Apr 22 '14 at 19:54
  • Why can't you do what I asked? Please try harder. – David Heffernan Apr 22 '14 at 19:57
  • I see that there are many uncultured people in this social, they only know "pressing vote down button" but even give a help. – user3560787 Apr 22 '14 at 19:58
  • Why my question is -4? Have you ever asked someone when you were beginner? – user3560787 Apr 22 '14 at 19:59
  • 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? – Jerry Dodge Apr 22 '14 at 20:00
  • I quit! Have you ever asked your teacher? – user3560787 Apr 22 '14 at 20:01
  • @JerryDodge I'm learning, sir! – user3560787 Apr 22 '14 at 20:04
  • This might be helpful (it is a bit more complicated): http://www.delphibasics.co.uk/Article.asp?Name=Pointers –  Apr 22 '14 at 20:04
  • 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. – Captain Obvlious Apr 22 '14 at 20:05
  • @CaptainObvlious So do you think how old I am? 5? – user3560787 Apr 22 '14 at 20:06
  • I've just edited my code. Please take a look. – user3560787 Apr 22 '14 at 20:15
  • @user3560787 For the record, just in the past 24 hours or so, I've seen at least 3-4 very similar questions deleted from Stack Overflow for the same reason. They're all "Converting my code from this language to that language". I just reversed my downvote after you edited your question to include a better code sample and your Delphi attempt. – Jerry Dodge Apr 22 '14 at 20:22
  • With the latest edit, I'm starting to understand the underlying issue. Hang on a few... – Mason Wheeler Apr 22 '14 at 20:23
  • @JerryDodge Please take a look at my new code – user3560787 Apr 22 '14 at 20:24
  • So you're trying to shift all the values in the array, correct? – Jerry Dodge Apr 22 '14 at 20:26
  • @JerryDodge Yes sir, can you explain why the last code in Delphi doesn't work? – user3560787 Apr 22 '14 at 20:33
  • It appears Mason's working on an answer for you, I believe – Jerry Dodge Apr 22 '14 at 20:34
  • 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. – David Heffernan Apr 22 '14 at 20:43
  • Gotta agree with David here. "It doesn't work" are the least useful words in the history of error reporting. Much more helpful is *explaining what you expect and what you're seeing instead;* that gives people something to work with. – Mason Wheeler Apr 22 '14 at 20:45

2 Answers2

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);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Your code does exactly what C++ does. +1 for you. And thank you very much, sir! :) – user3560787 Apr 22 '14 at 21:26
  • 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. – user3560787 Apr 23 '14 at 03:54
  • The C++ code leaks too. What is the context of this code. – David Heffernan Apr 23 '14 at 04:21
  • @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. – Remy Lebeau Apr 23 '14 at 04:32
  • Inc is the best and closest translation for `+=`. Please don't tell people not to edit answers. It's an important part of how SO works. For instance: http://stackoverflow.com/questions/23214528/delphi-xe4-octal-constant-is-working-like-decimal-constant/23214601#23214601 – David Heffernan Apr 23 '14 at 04:34
  • 1
    @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. – Mason Wheeler Apr 23 '14 at 12:09
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. :)

Mason Wheeler
  • 82,511
  • 50
  • 270
  • 477
  • @mason What forms of UB exist in C++ that do not in Delphi? – David Heffernan Apr 22 '14 at 21:52
  • 1
    @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. – Mason Wheeler Apr 22 '14 at 22:35
  • But if coded properly in the first place, shouldn't make a difference in the end :-) – Jerry Dodge Apr 22 '14 at 23:22
  • 1
    @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. – Mason Wheeler Apr 22 '14 at 23:24
  • 1
    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. – Jerry Dodge Apr 22 '14 at 23:25
  • @Mason The Delphi equivalent to the C++ code is UB just the same. It's wrong to compare C++ pointers to Delphi dynamic arrays. Try `std::vector`. – David Heffernan Apr 23 '14 at 04:33
  • @Mason I actually think that you don't really understand the difference between C and C++. I think you imagine C++ programmers routinely using raw pointers and new to allocate arrays. That's not how it is. Your statement about UB belies a lack of knowledge. Your answer here is excellent. I just find the C++ is terrible, Delphi is wonderful jibe rather grating. I think it would do you good to learn what good C++ looks like. You might be pleasantly surprised. – David Heffernan Apr 24 '14 at 05:57
  • @David: Yeah, that's the thing. I don't believe that "good C++" exists. Not when the language is filled with so many fundamental, language-level flaws that can't be fixed without turning it into a completely different language that is no longer C++. Look back at the history of the evolution of the language, from the beginning to C++ '11, and look at how many "new language features" are simply patches to C++ problems that don't exist in most other languages, rather than actual advances like you get in languages that were actually well-designed and thought through. – Mason Wheeler Apr 24 '14 at 17:29
  • C++ may not be the worst language ever created, but without a doubt it is the worst to ever be taken seriously. – Mason Wheeler Apr 24 '14 at 17:29
  • @Mason Delphi allows me to allocate memory with GetMem and access it out of bounds. Your criticisms apply to Delphi too. I suspect C++ has more wrinkles. But if you code well in C++ it can be as safe as well coded Delphi. You just have to understand the language well. – David Heffernan Apr 24 '14 at 17:31
  • @DavidHeffernan: Yeah, but who does that? I don't think I've ever, ever used `GetMem` for anything, not as a Delphi n00b and not as an experienced developer. I use `New` occasionally, (for records,) but most of the time if I'm in that position, I use a class instead, as they're more convenient. Doing the right thing in Delphi is easy and intuitive. But when I was learning C++ in college, *the very first things* they taught us were how to program C style, with raw pointers everywhere. It was over a year before we even learned of the existence of templates, vectors, smart pointers, etc. – Mason Wheeler Apr 24 '14 at 18:13
  • @Mason Your argument is bogus. Real C++ developers use std::vector. They don't use raw pointers. It silly to judge C++ on the basis of crap C++ code. I don't think you acknowledge that C++ now is not the same as it was 20 years ago. Also, college teachers are probably the worst people to learn C++ from. Try Accelerated C++ by Koenig and Moo. – David Heffernan Apr 24 '14 at 18:17
  • @David: 20 years ago, objects were value types, which tossed Liskov substitution out the window and means you need dreadful hacks like copy constructors. 20 years ago, there was no try/finally. 20 years ago, there was a badly broken, over-complicated, Turing-complete template system in the compiler that could (literally) take forever to compile what looks like simple code. 20 years ago, there was no real string or array types in the language and you had to rely on libraries (even if they are the standard library.) Has any of that changed? – Mason Wheeler Apr 24 '14 at 18:22
  • @Mason There's no point in arguing with somebody who displays the ignorance that you do. The C++ that you describe is terrible. But it's not C++ that the real world uses. Denying that the standard containers are part of C++ is shockingly ignorant. They are part of the ISO standard for crying out loud. If a C++ guru came along and said Delphi was terrible and justified it with comments based on 20 year old Delphi, how would you react? – David Heffernan Apr 24 '14 at 18:34
  • @DavidHeffernan: That would depend on whether or not his criticisms had been addressed in the last 20 years. I didn't say that they aren't "part of C++", but that they're not recognized by the language. For example, if I say `"foo"`, its type is `char*`, not `std::string`. If I declare an int array, I don't get a vector. **That. Has. Not. Been. Fixed.** Doing things "the right way" requires you to do something other than what is built into the language and looks obvious and intuitive, and worse still, it requires you to ugly your code up with colon::cancer all::over the::place. – Mason Wheeler Apr 24 '14 at 18:40
  • @Mason You basically don't know anything deep about C++ and have misdiagnosed your ignorance as a deficiency in C++. Your arguments in that last comment demonstrate that you do not understand that which you criticise. – David Heffernan Apr 24 '14 at 18:45
  • @David: I'm citing simple facts that anyone can verify. You keep calling this ignorance, with nothing to back it up. I'm just wrong because I'm wrong because I'm wrong, apparently, and who cares about the facts? Has objects-as-value-types been fixed? Of course not. Have templates been fixed? Can't be done; it would destroy existing code. These are simple, inarguable facts. Where are your facts to the contrary? – Mason Wheeler Apr 24 '14 at 19:00
  • @Mason Let's stick on one thing at a time. We can come back to these other criticisms of yours later. Let's wrap up arrays. You claim that C++ is bad because it offers no protection against buffer overrun in arrays. I say that C++ programmers use standard containers which do indeed offer that protection. Can we agree that your criticism there is invalid. – David Heffernan Apr 24 '14 at 19:03
  • @David: You're making a very different point than I am, and one that would not sound at all out of place prepended by the words "no true Scotsman." Yes, C++ programmers use the safe standard library routines *if they have learned to do so,* but the language itself goes out of its way to make this difficult, because the language's built-in string and array types are something completely different (and unsafe). And that's something that's never been fixed, nor do I think it *can* be fixed without breaking tons of code. The point I'm making is that in Delphi, *doing the intuitive thing works.* – Mason Wheeler Apr 24 '14 at 19:08
  • I just don't buy that argument at all. I guess we disagree. – David Heffernan Apr 24 '14 at 19:10
  • @David: Again, present facts, and I will listen. Tell me I'm wrong because I'm wrong because I'm wrong, and who can blame me for not agreeing with your (lack of) reasoning? – Mason Wheeler Apr 24 '14 at 19:15
  • Well, C++ without the standard library is lacking. I agree with that. It's a different story if you admit the existence of the standard library. We can't really have meaningful debate if you want to judge C++ without standard lib against modern Delphi. Do I get to declare that the comparison must be against Delphi 1? Am I allowed to deny the existence of Delphi dynamic arrays? – David Heffernan Apr 24 '14 at 19:28
  • Another problem you have seems to be the belief that features only count if they are defined in the language rather than the library. Different languages take different design decisions. In the case of C++ it has decided to build containers in the library rather than the language. – David Heffernan Apr 24 '14 at 19:30
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/51379/discussion-between-mason-wheeler-and-david-heffernan) – Mason Wheeler Apr 24 '14 at 20:37