www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How to use sprintf

reply Justin Hanekom <justin.hanekom gmail.com> writes:
Hi all,

I have what should be an *extremely* simple question that Im banging my head
against: how to use
sprintf to format something to a string.

I have tried:
  import std.stdio;
  ...
  auto buffer = new char[12];
  auto chars_written = sprintf(cast(char *) buffer, "%d", 12345);
  writeln(chars_written);
and various other ways of getting the buffer into sprintf, but no matter what I
do the program seems to
die when sprintf is called.

What I'm ultimately trying to do here is format a number with thousands
separated by commas.

Any idea?

Thanks, Justin
Apr 24 2011
next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
On 4/24/2011 5:22 PM, Justin Hanekom wrote:
 Hi all,

 I have what should be an *extremely* simple question that Im banging my head
against: how to use
 sprintf to format something to a string.

 I have tried:
    import std.stdio;
    ...
    auto buffer = new char[12];
    auto chars_written = sprintf(cast(char *) buffer, "%d", 12345);
    writeln(chars_written);
 and various other ways of getting the buffer into sprintf, but no matter what
I do the program seems to
 die when sprintf is called.

 What I'm ultimately trying to do here is format a number with thousands
separated by commas.

 Any idea?

 Thanks, Justin

sprintf is a C function. The string you passed needs to be zero-terminated. Since it's not, sprintf probably keeps trying to write more stuff until it segfaults, because it never finds the zero terminator. See std.string.toStringz (http://www.digitalmars.com/d/2.0/phobos/std_string.html#toStringz).
Apr 24 2011
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sun, 24 Apr 2011 17:22:39 -0400, dsimcha <dsimcha yahoo.com> wrote:

 On 4/24/2011 5:22 PM, Justin Hanekom wrote:
 Hi all,

 I have what should be an *extremely* simple question that Im banging my  
 head against: how to use
 sprintf to format something to a string.

 I have tried:
    import std.stdio;
    ...
    auto buffer = new char[12];
    auto chars_written = sprintf(cast(char *) buffer, "%d", 12345);
    writeln(chars_written);
 and various other ways of getting the buffer into sprintf, but no  
 matter what I do the program seems to
 die when sprintf is called.

 What I'm ultimately trying to do here is format a number with thousands  
 separated by commas.

 Any idea?

 Thanks, Justin

sprintf is a C function. The string you passed needs to be zero-terminated. Since it's not, sprintf probably keeps trying to write more stuff until it segfaults, because it never finds the zero terminator. See std.string.toStringz (http://www.digitalmars.com/d/2.0/phobos/std_string.html#toStringz).

This is not true. sprintf does not care if the destination buffer is zero terminated, because it actually writes the zero. The requirement is simply that the buffer be large enough to handle the data. Even the safer version of sprintf (snprintf) does not require the buffer to be zero-terminated before calling the function. The problem the OP has is he is casting buffer to a char *. He should just use buffer.ptr. This should work: auto chars_written = sprintf(buffer.ptr, "%d", 12345); -Steve
Apr 25 2011
parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 25/04/2011 15:56, Vladimir Panteleev wrote:
 On Mon, 25 Apr 2011 17:19:12 +0300, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:

 The problem the OP has is he is casting buffer to a char *. He should
 just use buffer.ptr.

Casting a string to char* is exactly the same as using the .ptr property, as far as generated code is concerned.

Not when a string is defined internally as struct { size_t length; immutable(char)* ptr; }. Casting to char* is a pointer to the start of the length, not the pointer. -- Robert http://octarineparrot.com/
Apr 25 2011
next sibling parent Robert Clipsham <robert octarineparrot.com> writes:
On 25/04/2011 16:26, Vladimir Panteleev wrote:
 On Mon, 25 Apr 2011 18:21:16 +0300, Robert Clipsham
 <robert octarineparrot.com> wrote:

 On 25/04/2011 15:56, Vladimir Panteleev wrote:
 On Mon, 25 Apr 2011 17:19:12 +0300, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:

 The problem the OP has is he is casting buffer to a char *. He should
 just use buffer.ptr.

Casting a string to char* is exactly the same as using the .ptr property, as far as generated code is concerned.

Not when a string is defined internally as struct { size_t length; immutable(char)* ptr; }. Casting to char* is a pointer to the start of the length, not the pointer.

Try it.

That's weird, I really didn't expect that :< Don't suppose you could explain why this behavior occurs? -- Robert http://octarineparrot.com/
Apr 25 2011
prev sibling next sibling parent Robert Clipsham <robert octarineparrot.com> writes:
On 25/04/2011 16:36, Steven Schveighoffer wrote:
 Try it.

I thought that "feature" was removed from D2? Just tested it, and it's definitely not removed yet. But it will be :) -Steve

Thanks for putting my mind at ease, I just spent ten minutes writing various variations and disassembling them trying to figure out what was going on! -- Robert http://octarineparrot.com/
Apr 25 2011
prev sibling next sibling parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 25.04.2011 17:36, schrieb Steven Schveighoffer:
 On Mon, 25 Apr 2011 11:26:57 -0400, Vladimir Panteleev
 <vladimir thecybershadow.net> wrote:
 
 On Mon, 25 Apr 2011 18:21:16 +0300, Robert Clipsham
 <robert octarineparrot.com> wrote:

 On 25/04/2011 15:56, Vladimir Panteleev wrote:
 On Mon, 25 Apr 2011 17:19:12 +0300, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:

 The problem the OP has is he is casting buffer to a char *. He should
 just use buffer.ptr.

Casting a string to char* is exactly the same as using the .ptr property, as far as generated code is concerned.

Not when a string is defined internally as struct { size_t length; immutable(char)* ptr; }. Casting to char* is a pointer to the start of the length, not the pointer.

Try it.

I thought that "feature" was removed from D2? Just tested it, and it's definitely not removed yet. But it will be :) -Steve

I don't think it's a good idea to remove it - that would probably (silently) break a lot of code. As I see it there are two possibilities to remove it: 1. completely forbid casting an array to a pointer (even to get the address of the struct) - I don't think this is desirable? 2. silently change the behaviour to return the address of the struct instead of .ptr - silently breaks code, even worse. So why not just leave it the way it is? Cheers, - Daniel
Apr 25 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Daniel Gibson:

 So why not just leave it the way it is?

It muds the semantic of the language, adding another special case. I think the right (right = shared with other structs) semantics here is to return the address of the length field. My experience based seeing it happen again and again tells me that every time you leave some muddy semantics in a language, sooner or later that comes back to bite your bum. Another example is the property semantics, some people don't want to fix the current wrong behaviour. Bye, bearophile
Apr 25 2011
parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 25.04.2011 19:30, schrieb bearophile:
 Daniel Gibson:
 
 So why not just leave it the way it is?

It muds the semantic of the language, adding another special case. I think the right (right = shared with other structs) semantics here is to return the address of the length field.

No. Casting other structs (*not* pointer to struct) is in fact illegal. (This just occured to me, I didn't think of this when writing the other post) If you want the address of the struct you write void *foo = cast(void*)&s; So the only sane thing to do is either to forbid casting an array to a pointer or to return .ptr like it's done now. I don't see the harm in the latter, but then again arr.ptr is shorter and more readable. So my only remaining objection is: Allowing it doesn't hurt (IMHO) and disallowing may break existing code, so why bother ;) Cheers, - Daniel
Apr 25 2011
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Daniel Gibson:

 No. Casting other structs (*not* pointer to struct) is in fact illegal.
 (This just occured to me, I didn't think of this when writing the other
 post)

Right, sorry.
 So my only remaining objection is: Allowing it doesn't hurt (IMHO) and
 disallowing may break existing code, so why bother ;)

It makes the language more ugly, more complex, and it will cause bugs and problems, as all other similar muddy shortcuts. I have a bug report about this that is sleeping there since 2010-03-20, among several other reports of similar anti-features: http://d.puremagic.com/issues/show_bug.cgi?id=3990 I don't need a perfect language, but I fail to understand why similar little pieces of trash are wanted in any language. bearophile
Apr 25 2011
parent Adam D. Ruppe <destructionator gmail.com> writes:
bearophile:
 I don't need a perfect language, but I fail to understand why
 similar little pieces of trash are wanted in any language.

It's probably meant to make interaction with C a little easier. In C, arrays and pointers are interchangeable in a lot of places. It'd make D code look more like the C code it is interacting with. I don't think we need it, since the .ptr property does the job, but the reasoning probably made a lot of sense at the time it was brought in.
Apr 25 2011
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Steven Schveighoffer:

 simpler language spec/compiler :)

Here there are several people that use D that find surprising things in a tiny piece of code, and discuss about it with many posts. This is the best demonstration that this is a special case that adds complexity to the language, that needs to be removed. A special case is worth keeping only in special situations, only when it gives a significant advantage. This is not the case. Bye, bearophile
Apr 25 2011
prev sibling next sibling parent reply Alexander <aldem+dmars nk7.net> writes:
On 25.04.2011 17:36, Steven Schveighoffer wrote:

 Not when a string is defined internally as struct { size_t length;
immutable(char)* ptr; }. Casting to char* is a pointer to the start of the
length, not the pointer.

Try it.

I thought that "feature" was removed from D2? Just tested it, and it's definitely not removed yet. But it will be :)

How exactly this feature will be removed? Disallowing opCast() which does this explicitly? ;) Regards, /Alexander
Apr 26 2011
parent reply Alexander <aldem+dmars nk7.net> writes:
On 26.04.2011 13:59, Steven Schveighoffer wrote:

 Currently, casting an array to a pointer is a special case of casting in the
compiler, which basically returns arr.ptr.  However, that functionality is
already available via arr.ptr.

To me (coming from C/C++) it looks more natural to cast instead if using arr.ptr. After all, array is a pointer (=reference), and arrays are not structs (=values), so I see no reason to disallow this, to be honest. And, indeed, once disallowed, it will break a lot of existing code... /Alexander
Apr 26 2011
next sibling parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 26.04.2011 15:11, schrieb Alexander:
 After all, array is a pointer (=reference), and arrays are not structs
(=values), so I see no reason to disallow this, to be honest.
 

No, in D arrays are not just pointers. It's indeed a struct that contains the length (arr.length) and the pointer (arr.ptr). This makes arrays in D a lot safer and also easier to use than in C. Cheers, - Daniel
Apr 26 2011
parent reply Alexander <aldem+dmars nk7.net> writes:
On 26.04.2011 15:21, Daniel Gibson wrote:

 No, in D arrays are not just pointers. It's indeed a struct that
 contains the length (arr.length) and the pointer (arr.ptr).

If this is a struct, then there is no "special compiler handling" needed to cast a struct to a pointer using opCast() (except for static arrays). But, from programmer point of view, array is not a struct, just a type with some properties, "struct" is hidden somewhere internally.
 This makes arrays in D a lot safer and also easier to use than in C.

I see no danger in using cast(void *)Array instead of Array.ptr, if semantic is known in advance (and it is). IMHO, it would be not so good if this handling will be disallowed at some point. /Alexander
Apr 26 2011
parent Alexander <aldem+dmars nk7.net> writes:
On 26.04.2011 19:15, Steven Schveighoffer wrote:

 In other words, casting an array to a pointer is first of all a hack, and
second of all 100% unnecessary.  It's just wasting compiler code space.

Indeed, your arguments are very convincing - being a person like "I know what I'm doing" I typically forget about those things... Then, there is one issue left - old code... :) /Alexander
Apr 26 2011
prev sibling parent Peter Alexander <peter.alexander.au gmail.com> writes:
On 26/04/11 2:11 PM, Alexander wrote:
 On 26.04.2011 13:59, Steven Schveighoffer wrote:

 Currently, casting an array to a pointer is a special case of casting in the
compiler, which basically returns arr.ptr.  However, that functionality is
already available via arr.ptr.

To me (coming from C/C++) it looks more natural to cast instead if using arr.ptr. After all, array is a pointer (=reference), and arrays are not structs (=values), so I see no reason to disallow this, to be honest. And, indeed, once disallowed, it will break a lot of existing code... /Alexander

This is wrong on two levels: 1. In D, an array is not a pointer. It is a struct with two members: a length and a pointer. It is not the same as C or C++ array. 2. Even in C++, an array is not a pointer. The type of an array in C++ is T[N] whereas a pointer is T*. The only reasons you can pass an array into a function that accepts a pointer is because of an implicit conversion. Arrays are implemented as pointers, but they are not the same type.
Apr 26 2011
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
 Isn't it dangerous to pass a D string and let the C code overwrite the
 string, regardless of char* vs .ptr field?

There is a possibility for buffer overflow.
Apr 26 2011
parent bearophile <bearophileHUGS lycos.com> writes:
Steven Schveighoffer:

 D would not allow you to pass a .ptr field of an immutable string, because  
 the type would be immutable(char)* and wouldn't implicitly cast to the  
 required char* argument.  Casting, however, would mask that problem and  
 probably overwrite immutable data (and probably segfault on Linux).   
 Another example of why casting is bad.

Casting is dangerous in general, but it becomes less dangerous when you have some different specialized casts: if you have a cast syntax that only change the const-ness of something (mutable <-> const <-> immutable), and a different syntax (syntax = "any way to express a semantics") to change other aspects of the type, it becomes less easy to cast const-ness away by mistake. Bye, bearophile
Apr 26 2011
prev sibling next sibling parent "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Mon, 25 Apr 2011 17:19:12 +0300, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 The problem the OP has is he is casting buffer to a char *.  He should  
 just use buffer.ptr.

Casting a string to char* is exactly the same as using the .ptr property, as far as generated code is concerned. -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Apr 25 2011
prev sibling next sibling parent "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Mon, 25 Apr 2011 18:21:16 +0300, Robert Clipsham  
<robert octarineparrot.com> wrote:

 On 25/04/2011 15:56, Vladimir Panteleev wrote:
 On Mon, 25 Apr 2011 17:19:12 +0300, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:

 The problem the OP has is he is casting buffer to a char *. He should
 just use buffer.ptr.

Casting a string to char* is exactly the same as using the .ptr property, as far as generated code is concerned.

Not when a string is defined internally as struct { size_t length; immutable(char)* ptr; }. Casting to char* is a pointer to the start of the length, not the pointer.

Try it. -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Apr 25 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 25 Apr 2011 11:26:57 -0400, Vladimir Panteleev  
<vladimir thecybershadow.net> wrote:

 On Mon, 25 Apr 2011 18:21:16 +0300, Robert Clipsham  
 <robert octarineparrot.com> wrote:

 On 25/04/2011 15:56, Vladimir Panteleev wrote:
 On Mon, 25 Apr 2011 17:19:12 +0300, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:

 The problem the OP has is he is casting buffer to a char *. He should
 just use buffer.ptr.

Casting a string to char* is exactly the same as using the .ptr property, as far as generated code is concerned.

Not when a string is defined internally as struct { size_t length; immutable(char)* ptr; }. Casting to char* is a pointer to the start of the length, not the pointer.

Try it.

I thought that "feature" was removed from D2? Just tested it, and it's definitely not removed yet. But it will be :) -Steve
Apr 25 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 25 Apr 2011 11:26:57 -0400, Vladimir Panteleev  
<vladimir thecybershadow.net> wrote:

 On Mon, 25 Apr 2011 18:21:16 +0300, Robert Clipsham  
 <robert octarineparrot.com> wrote:

 On 25/04/2011 15:56, Vladimir Panteleev wrote:
 On Mon, 25 Apr 2011 17:19:12 +0300, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:

 The problem the OP has is he is casting buffer to a char *. He should
 just use buffer.ptr.

Casting a string to char* is exactly the same as using the .ptr property, as far as generated code is concerned.

Not when a string is defined internally as struct { size_t length; immutable(char)* ptr; }. Casting to char* is a pointer to the start of the length, not the pointer.

Try it.

BTW, that got me curious what the real failure of the original code was, and I tried it. Turns out, it actually runs successfully! So I can only guess that the OP didn't post his actually failing code. -Steve
Apr 25 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 25 Apr 2011 11:39:28 -0400, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 On Mon, 25 Apr 2011 11:26:57 -0400, Vladimir Panteleev  
 <vladimir thecybershadow.net> wrote:

 On Mon, 25 Apr 2011 18:21:16 +0300, Robert Clipsham  
 <robert octarineparrot.com> wrote:

 On 25/04/2011 15:56, Vladimir Panteleev wrote:
 On Mon, 25 Apr 2011 17:19:12 +0300, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:

 The problem the OP has is he is casting buffer to a char *. He should
 just use buffer.ptr.

Casting a string to char* is exactly the same as using the .ptr property, as far as generated code is concerned.

Not when a string is defined internally as struct { size_t length; immutable(char)* ptr; }. Casting to char* is a pointer to the start of the length, not the pointer.

Try it.

BTW, that got me curious what the real failure of the original code was, and I tried it. Turns out, it actually runs successfully! So I can only guess that the OP didn't post his actually failing code.

Regardless of all this, cast(char *)buffer is *not* recommended D code, and will likely fail in some future 2.x version of the compiler. Man, I should learn to collect all my thoughts before posting :) -Steve
Apr 25 2011
prev sibling next sibling parent "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Mon, 25 Apr 2011 18:42:32 +0300, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 Regardless of all this, cast(char *)buffer is *not* recommended D code,  
 and will likely fail in some future 2.x version of the compiler.

I'm pretty sure I learned of this trick from reading some Phobos code. Perhaps this behavior was implemented before the .ptr property for dynamic arrays? -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Apr 25 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Isn't it dangerous to pass a D string and let the C code overwrite the
string, regardless of char* vs .ptr field?
Apr 25 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 25 Apr 2011 12:47:20 -0400, Daniel Gibson <metalcaedes gmail.com>  
wrote:

 Am 25.04.2011 17:36, schrieb Steven Schveighoffer:
 On Mon, 25 Apr 2011 11:26:57 -0400, Vladimir Panteleev
 <vladimir thecybershadow.net> wrote:

 On Mon, 25 Apr 2011 18:21:16 +0300, Robert Clipsham
 <robert octarineparrot.com> wrote:

 On 25/04/2011 15:56, Vladimir Panteleev wrote:
 On Mon, 25 Apr 2011 17:19:12 +0300, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:

 The problem the OP has is he is casting buffer to a char *. He  
 should
 just use buffer.ptr.

Casting a string to char* is exactly the same as using the .ptr property, as far as generated code is concerned.

Not when a string is defined internally as struct { size_t length; immutable(char)* ptr; }. Casting to char* is a pointer to the start of the length, not the pointer.

Try it.

I thought that "feature" was removed from D2? Just tested it, and it's definitely not removed yet. But it will be :) -Steve

I don't think it's a good idea to remove it - that would probably (silently) break a lot of code. As I see it there are two possibilities to remove it: 1. completely forbid casting an array to a pointer (even to get the address of the struct) - I don't think this is desirable?

The address of the struct is &arr. There is no conflict here, and I believe this is the solution that will be implemented. I thought the compiler disabled this "feature" a while ago, I know that Don went through and removed all the casts that were in the runtime. -Steve
Apr 25 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 25 Apr 2011 12:55:38 -0400, Andrej Mitrovic  
<andrej.mitrovich gmail.com> wrote:

 Isn't it dangerous to pass a D string and let the C code overwrite the
 string, regardless of char* vs .ptr field?

Yes. Using sprintf is dangerous regardless of what language you are using. It is advised to use D equivalents. -Steve
Apr 25 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 25 Apr 2011 13:40:30 -0400, Daniel Gibson <metalcaedes gmail.com>  
wrote:

 Am 25.04.2011 19:30, schrieb bearophile:
 Daniel Gibson:

 So why not just leave it the way it is?

It muds the semantic of the language, adding another special case. I think the right (right = shared with other structs) semantics here is to return the address of the length field.

No. Casting other structs (*not* pointer to struct) is in fact illegal. (This just occured to me, I didn't think of this when writing the other post) If you want the address of the struct you write void *foo = cast(void*)&s; So the only sane thing to do is either to forbid casting an array to a pointer or to return .ptr like it's done now. I don't see the harm in the latter, but then again arr.ptr is shorter and more readable. So my only remaining objection is: Allowing it doesn't hurt (IMHO) and disallowing may break existing code, so why bother ;)

simpler language spec/compiler :) -Steve
Apr 25 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 26 Apr 2011 06:31:39 -0400, Alexander <aldem+dmars nk7.net> wrote:

 On 25.04.2011 17:36, Steven Schveighoffer wrote:

 Not when a string is defined internally as struct { size_t length;  
 immutable(char)* ptr; }. Casting to char* is a pointer to the start  
 of the length, not the pointer.

Try it.

I thought that "feature" was removed from D2? Just tested it, and it's definitely not removed yet. But it will be :)

How exactly this feature will be removed? Disallowing opCast() which does this explicitly? ;)

Currently, casting an array to a pointer is a special case of casting in the compiler, which basically returns arr.ptr. However, that functionality is already available via arr.ptr. I think the special case can be disallowed. opCast will remain as-is. -Steve
Apr 26 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/26/11, Timon Gehr <timon.gehr gmx.ch> wrote:
 Isn't it dangerous to pass a D string and let the C code overwrite the
 string, regardless of char* vs .ptr field?

There is a possibility for buffer overflow.

No, I mean the C function will overwrite an immutable string.
Apr 26 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 26 Apr 2011 10:08:21 -0400, Alexander <aldem+dmars nk7.net> wrote:

 On 26.04.2011 15:21, Daniel Gibson wrote:

 No, in D arrays are not just pointers. It's indeed a struct that
 contains the length (arr.length) and the pointer (arr.ptr).

If this is a struct, then there is no "special compiler handling" needed to cast a struct to a pointer using opCast() (except for static arrays). But, from programmer point of view, array is not a struct, just a type with some properties, "struct" is hidden somewhere internally.

A "struct" is simply a group of members used as data, and a group of functions that accept that member as the first parameter. The same is true for arrays, although it's not defined anywhere as a "struct." Arrays are special types to the compiler, they are not ordinary structures. However, more and more they are being extended in the library. In reality, they could just be treated as normal types with the library defining the properties, thanks to the ability to add array properties. Already associative arrays are done that way. The way it is implemented is a mix between newer style functions defined in the library and original functions that were done way back when D did not have the ability to add array properties.
 This makes arrays in D a lot safer and also easier to use than in C.

I see no danger in using cast(void *)Array instead of Array.ptr, if semantic is known in advance (and it is).

Casting overrides the type system. It's always a red flag. Example: void foo() { char[] buffer = new char[12]; ... auto charptr = cast(char *)buffer; sometime down the road, you decide buffer should be a const input parameter: void foo(const(char)[] buffer) { ... auto charptr = cast(char *)buffer; // oops! there goes const! or if you decide later to use wchar[], or whatever. casting says "I know what I'm doing" and should be only used very sparingly. It should not be a tool of first resort. compare that to: char *charptr = buffer.ptr; // throws an error if buffer is not a char[] or even more robust: auto charptr = buffer.ptr; // now all your code is upgraded to use the newest type you decide on. In other words, casting an array to a pointer is first of all a hack, and second of all 100% unnecessary. It's just wasting compiler code space. -Steve
Apr 26 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 26 Apr 2011 13:11:20 -0400, Andrej Mitrovic  
<andrej.mitrovich gmail.com> wrote:

 On 4/26/11, Timon Gehr <timon.gehr gmx.ch> wrote:
 Isn't it dangerous to pass a D string and let the C code overwrite the
 string, regardless of char* vs .ptr field?

There is a possibility for buffer overflow.

No, I mean the C function will overwrite an immutable string.

D would not allow you to pass a .ptr field of an immutable string, because the type would be immutable(char)* and wouldn't implicitly cast to the required char* argument. Casting, however, would mask that problem and probably overwrite immutable data (and probably segfault on Linux). Another example of why casting is bad. for example, this should throw an error: import std.stdio; void main() { sprintf("buf".ptr, "%d", 12345); } -Steve
Apr 26 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/26/11, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 On Tue, 26 Apr 2011 13:11:20 -0400, Andrej Mitrovic
 <andrej.mitrovich gmail.com> wrote:

 On 4/26/11, Timon Gehr <timon.gehr gmx.ch> wrote:
 Isn't it dangerous to pass a D string and let the C code overwrite the
 string, regardless of char* vs .ptr field?

There is a possibility for buffer overflow.

No, I mean the C function will overwrite an immutable string.

D would not allow you to pass a .ptr field of an immutable string, because the type would be immutable(char)* and wouldn't implicitly cast to the required char* argument. Casting, however, would mask that problem and probably overwrite immutable data (and probably segfault on Linux). Another example of why casting is bad. for example, this should throw an error: import std.stdio; void main() { sprintf("buf".ptr, "%d", 12345); } -Steve

Yes I was refering to casting. It would segfault on Linux but probably not on Windows, which brings us to the infamous string literal assignment bug: void main() { "hello" = "red"; string x = "hello"; assert(x == "red"); } http://d.puremagic.com/issues/show_bug.cgi?id=4539
Apr 26 2011
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 26 Apr 2011 16:27:00 -0400, Alexander <aldem+dmars nk7.net> wrote:

   Then, there is one issue left - old code... :)

The compiler should tell you all the places where you have to fix the old code ;) -Steve
Apr 26 2011
prev sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
You might try the format() function instead:

http://dpldocs.info/std.string.format

Though, I don't think it does thousands grouping, so it might not
work for you.

If you need C's sprintf, make sure the strings are zero terminated
and that you're passing pointers to them:

char[10] buffer;

sprintf(buffer.ptr, toStringz(formatString), args...);
Apr 24 2011
parent reply Justin Hanekom <justin.hanekom gmail.com> writes:
Thanks Adam,

My main problem, I guess, is that I can't seem to find the documentation for
these
functions in D.  I'll be checking out the link you sent for the format function
shortly.

I don't expect the function to be able to do the thousands formatting for me
(C's
version works if you use "%'d" [notice the '] and have LC_LOCALE set) but just
want to get a string that I can then format.

Thanks for your speedy, detailed, and very informative reply!

Justin
Apr 24 2011
parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
If you just want to format a string use std.string.format.

import std.string;

int i=1;
float f=2.5f;
string s = "test";
string output = format("%s %s %s",i,f,s);

If you use the %s placeholder the type will automatically be determined 
and printed out correctly.
-- 
Kind Regards
Benjamin Thaut
Apr 24 2011
parent %Justin Hanekom <justin.hanekom gmail.com> writes:
Thanks dsimcha, Ben, and Adam,

You guys are great!
Apr 24 2011