digitalmars.D - Disallow arrays as pointers
- bearophile (33/33) Oct 30 2011 I have translated C code similar to:
- Jonathan M Davis (12/63) Oct 30 2011 Arrays in D implicitly convert to their ptr property, so they essentiall...
- bearophile (9/13) Oct 30 2011 How much code is broken by this?
- Jonathan M Davis (6/17) Oct 30 2011 I think that it will primarily affect strings (though in many such cases...
- bearophile (6/9) Oct 30 2011 That code works with an implicit conversion that saves the typing of 4 m...
- Timon Gehr (15/22) Oct 30 2011 I have never had a bug because of arrays implicitly converting to
- bearophile (7/12) Oct 30 2011 You see that D design tries hard to avoid the need to use pointers as mu...
- bearophile (5/7) Oct 30 2011 I think that a large part of that C syntactic elegance is an illusion. F...
- Timon Gehr (6/11) Oct 31 2011 I rarely use pointers in D, its arrays are a better concept. I just
- deadalnix (4/29) Nov 02 2011 Well you can do that in D. The thing is to not do it implicitely because...
- deadalnix (2/9) Oct 31 2011 That cannot be more true.
- Andrej Mitrovic (3/3) Oct 30 2011 I didn't know that would compile.
- Don (14/32) Oct 31 2011 What's New for D 0.177
- bearophile (46/46) Oct 31 2011 Kenji Hara (and the D community) is really good, he has already written ...
- Timon Gehr (17/61) Oct 31 2011 That is not similar code. This is:
- bearophile (18/47) Oct 31 2011 cast(char*) is D code, it's not a legacy C idiom, so you are writing it ...
- Timon Gehr (12/27) Nov 01 2011 That works without the ".ptr".
- bearophile (66/78) Nov 01 2011 Right. There is an implict conversion between the 2-word struct of the s...
- bearophile (14/21) Nov 01 2011 The situation is a bit more complex:
- deadalnix (5/28) Nov 02 2011 Well, because the ptr property is done for that. Actually, D ABI says
- Don (4/39) Nov 03 2011 The fix has already been implemented in git master. The bug report is
- Salih Dincer (7/100) May 13 2023 I saw that it was closed today:
- Salih Dincer (4/50) May 13 2023 A new issue has been reported by Steven Schveighoffer:
- Dejan Lekic (3/10) Nov 05 2011 It is not a bug, it is a feature. If you really do not like it, use
- Don (2/12) Nov 05 2011 It was a bug. And it's now been fixed.
- Dejan Lekic (3/5) Nov 07 2011 Don, care to explain why? If I want to treat D's array like I would do i...
- Don (8/13) Nov 09 2011 I had no involvement with it at all.
I have translated C code similar to: something foo(int n) { int *array = malloc(n * sizeof(int)); int i; for (...) { for (i = 0; i < n; i++, array++) { *array = ...; *array = ...; } ... } Into D2 code similar to: something foo(int n) { auto array = new int[n]; size_t index; foreach (...) { foreach (i; 0 .. n) { array[index] = ...; *array = ...; index++; } ... } Do you see the bug I have found during the debugging? I think the D2 compiler has to catch this bug: *array = ...; D arrays aren't pointers. Letting the compiler see them as pointers is bug-prone, not tidy, and doesn't help D newbies understand how D represents its arrays. My bug report: http://d.puremagic.com/issues/show_bug.cgi?id=3990 Some very good comments about this topic: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=135391 Bye, bearophile
Oct 30 2011
On Sunday, October 30, 2011 17:29:36 bearophile wrote:I have translated C code similar to: something foo(int n) { int *array = malloc(n * sizeof(int)); int i; for (...) { for (i = 0; i < n; i++, array++) { *array = ...; *array = ...; } ... } Into D2 code similar to: something foo(int n) { auto array = new int[n]; size_t index; foreach (...) { foreach (i; 0 .. n) { array[index] = ...; *array = ...; index++; } ... } Do you see the bug I have found during the debugging? I think the D2 compiler has to catch this bug: *array = ...; D arrays aren't pointers. Letting the compiler see them as pointers is bug-prone, not tidy, and doesn't help D newbies understand how D represents its arrays. My bug report: http://d.puremagic.com/issues/show_bug.cgi?id=3990 Some very good comments about this topic: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&ar ticle_id=135391Arrays in D implicitly convert to their ptr property, so they essentially _are_ pointers in that sense. Now, personally, I think that it would be a good idea for them _not_ to implicitly convert, forcing you to explicitly use the ptr property, since you really shouldn't be treating arrays as pointers in D code. It's primarily when interacting with C code that you need to do that sort of thing, and the ptr property deals with it just fine. However, I don't think that you're going to find a general consensus that the implicit conversion is bad, and changing it now would likely break a lot of code. So, while I do think that it would be a good change, I really don't think that it's going to happen at this point. - Jonathan M Davis
Oct 30 2011
Jonathan M Davis:However, I don't think that you're going to find a general consensus that the implicit conversion is bad,I'll keep count how many are against this idea.and changing it now would likely break a lot of code.How much code is broken by this? It's bad D code that's easy to fix adding a ".ptr", or using "-d" (deprecated) to compile the code. So, while I do think that it would be a good change, I really don'tthink that it's going to happen at this point.Let's break some code, to avoid even more bugs/breakage later! :-) (I am asking for some other little breaking changes in Bugzilla. This is not the only one.) Bye, bearophile
Oct 30 2011
On Sunday, October 30, 2011 18:10:06 bearophile wrote:Jonathan M Davis:I think that it will primarily affect strings (though in many such cases toStringz or toUTFz should generally be used), but from what I understand, it's quite common for D programmers interacting with C code to just pass arrays to C functions without using the ptr property. - Jonathan M DavisHowever, I don't think that you're going to find a general consensus that the implicit conversion is bad,I'll keep count how many are against this idea.and changing it now would likely break a lot of code.How much code is broken by this? It's bad D code that's easy to fix adding a ".ptr", or using "-d" (deprecated) to compile the code.
Oct 30 2011
Jonathan M Davis:from what I understand, it's quite common for D programmers interacting with C code to just pass arrays to C functions without using the ptr property.That code works with an implicit conversion that saves the typing of 4 more chars, while introducing something that is negative for both newbie D programmers and more trained ones. ".ptr" was introduced in D to avoid this. In general I find it curious that D design tries to avoid some mistakes of the C design, and to disallow some bug-prone features of C, like some implicit type conversions. But then, it seems that D doesn't take a lot of care to avoid bug-prone "features" that it has introduced, that were not present in C (like the one discussed here, like lax management of strings that represent operators of operator overloading, etc.) Thank you for your answers, bye, bearophile
Oct 30 2011
On 10/31/2011 12:03 AM, bearophile wrote:Jonathan M Davis:I have never had a bug because of arrays implicitly converting to pointers. I'd sometimes even like e.g. ++array to mean array=array[1..$]. A lot of C's carefully designed syntactic elegance is lost when going from pointers/iterators to arrays and ranges. But why is *array not bounds checked in non-release mode? I think it should be. The lax management of strings is not a bug-prone feature. (in the sense that it would be likely to produce erroneous code because of subtle typing mistakes.) Sure, if the implementer of the aggregate using operator overloading does not handle invalid sequences, it can be "exploited" to gain access to private members and/or implementation details. That does not happen by accident. I don't think Phobos helps enough to make correct handling easy, maybe some simple isOpBinary(string), isOpUnary(string), etc. templates would be worth adding.from what I understand, it's quite common for D programmers interacting with C code to just pass arrays to C functions without using the ptr property.That code works with an implicit conversion that saves the typing of 4 more chars, while introducing something that is negative for both newbie D programmers and more trained ones. ".ptr" was introduced in D to avoid this. In general I find it curious that D design tries to avoid some mistakes of the C design, and to disallow some bug-prone features of C, like some implicit type conversions. But then, it seems that D doesn't take a lot of care to avoid bug-prone "features" that it has introduced, that were not present in C (like the one discussed here, like lax management of strings that represent operators of operator overloading, etc.)
Oct 30 2011
Timon Gehr:I have never had a bug because of arrays implicitly converting to pointers.Good.A lot of C's carefully designed syntactic elegance is lost when going from pointers/iterators to arrays and ranges.You see that D design tries hard to avoid the need to use pointers as much as possible, because pointers are bug prone, give less readable code, and they are not needed in most cases (you use something a bit higher level, like arrays or references). Some people say that C language is as elegant as a katana sword, but I have to say that most times you want to keep it in its sheath :-)But why is *array not bounds checked in non-release mode? I think it should be.In D there are arrays, and there are pointers. Arrays are bound-checked, pointers aren't. So when you use arrays as pointers, or when you use somearray.ptr[x] you have lost array bounds. Adding a third intermediate type is not a good idea, it increases language and implementation complexity for a practice that is meant as discouraged since the introduction of the ptr field. Bye, bearophile
Oct 30 2011
Timon Gehr:A lot of C's carefully designed syntactic elegance is lost when going from pointers/iterators to arrays and ranges.I think that a large part of that C syntactic elegance is an illusion. From my experience, I want my code to look very simple to read and clean every time this is possible. I want it to be easy to port to other languages, because I have do it often enough. C code that uses lot of pointers is often bug-prone, messy and hard to safely translate to other languages. There are situation where pointers are necessary or are better than the alternatives, or they give the needed flexibility, so I prefer a language with pointers, but in a well designed language those situations are not common, and I think raw pointers should be avoided when they are not needed. I have debugged enough C code to be rather sure of this. Good luck with your pointers. Bye, bearophile
Oct 30 2011
On 10/31/2011 02:49 AM, bearophile wrote:Timon Gehr:I rarely use pointers in D, its arrays are a better concept. I just remarked that C code using pointers is sometimes more elegant than equivalent D code using arrays or ranges, and that it is a little bit unfortunate that we have all that while(*p && *p++ == --*q++){} stuff in the D grammar without the possibility to use it.A lot of C's carefully designed syntactic elegance is lost when going from pointers/iterators to arrays and ranges.I think that a large part of that C syntactic elegance is an illusion. From my experience, I want my code to look very simple to read and clean every time this is possible. I want it to be easy to port to other languages, because I have do it often enough. C code that uses lot of pointers is often bug-prone, messy and hard to safely translate to other languages. There are situation where pointers are necessary or are better than the alternatives, or they give the needed flexibility, so I prefer a language with pointers, but in a well designed language those situations are not common, and I think raw pointers should be avoided when they are not needed. I have debugged enough C code to be rather sure of this. Good luck with your pointers.
Oct 31 2011
Le 31/10/2011 21:35, Timon Gehr a écrit :On 10/31/2011 02:49 AM, bearophile wrote:Well you can do that in D. The thing is to not do it implicitely because it is a dangerous behaviour and you should go into this only if you know what you are doing and not by mistake.Timon Gehr:I rarely use pointers in D, its arrays are a better concept. I just remarked that C code using pointers is sometimes more elegant than equivalent D code using arrays or ranges, and that it is a little bit unfortunate that we have all that while(*p && *p++ == --*q++){} stuff in the D grammar without the possibility to use it.A lot of C's carefully designed syntactic elegance is lost when going from pointers/iterators to arrays and ranges.I think that a large part of that C syntactic elegance is an illusion. From my experience, I want my code to look very simple to read and clean every time this is possible. I want it to be easy to port to other languages, because I have do it often enough. C code that uses lot of pointers is often bug-prone, messy and hard to safely translate to other languages. There are situation where pointers are necessary or are better than the alternatives, or they give the needed flexibility, so I prefer a language with pointers, but in a well designed language those situations are not common, and I think raw pointers should be avoided when they are not needed. I have debugged enough C code to be rather sure of this. Good luck with your pointers.
Nov 02 2011
Le 30/10/2011 22:46, Jonathan M Davis a écrit :On Sunday, October 30, 2011 17:29:36 bearophile wrote: Arrays in D implicitly convert to their ptr property, so they essentially _are_ pointers in that sense. Now, personally, I think that it would be a good idea for them _not_ to implicitly convert, forcing you to explicitly use the ptr property, since you really shouldn't be treating arrays as pointers in D code. It's primarily when interacting with C code that you need to do that sort of thing, and the ptr property deals with it just fine.That cannot be more true.
Oct 31 2011
I didn't know that would compile. Anyway, if one really wants to treat arrays like pointers he can do: *array.ptr
Oct 30 2011
On 30.10.2011 22:29, bearophile wrote:I have translated C code similar to: something foo(int n) { int *array = malloc(n * sizeof(int)); int i; for (...) { for (i = 0; i< n; i++, array++) { *array = ...; *array = ...; } ... } Into D2 code similar to: something foo(int n) { auto array = new int[n];*array = ...;I think the D2 compiler has to catch this bug: *array = ...; D arrays aren't pointers. Letting the compiler see them as pointers is bug-prone, not tidy, and doesn't help D newbies understand how D represents its arrays.What's New for D 0.177 Dec 9, 2006 New/Changed Features Arrays no longer implicitly convert to pointers unless -d is used. For example, this code: void main() { int[] x = new int[59]; int *q = x; } compiled on 0.176 and earlier, but not any more. The case involving *arr seems to have just been missed. This is a simple accepts-invalid bug. Not an enhancement request.
Oct 31 2011
Kenji Hara (and the D community) is really good, he has already written a pull request with the bug fix: https://github.com/D-Programming-Language/dmd/pull/483 --------------------- Kenji Hara has fixed about 1/3 of the issue, so he asked me to split the but report, this is a spin off: http://d.puremagic.com/issues/show_bug.cgi?id=6869 In DMD 2.056 this code compiles: void main() { int[] a1 = [5, 4, 3]; int* p1 = cast(int*)a1; // no compile error here } Similar code using user-created struct doesn't compile: struct Foo { int* p; size_t n; } void main() { Foo f; auto x = cast(int*)f; // compile error here } I don't see the need to accept this cast, because we have said that D arrays are not pointers, and allowing the array to pointer cast means introducing/leaving an useless special case, and in practice this special case is not useful because arrays have the ptr property: struct Foo { int* p; size_t n; } void main() { Foo f; auto x = f.ptr; // OK } So I think cast(int*)a1 should be forbidden. ----------------------- The third part of the bug report was part of this older one: http://d.puremagic.com/issues/show_bug.cgi?id=3971 The idea is to forbid code like: void main() { int[3] a; a = 1; assert(a == [1, 1, 1]); } And require the square brackets every time an array operation is performed, for syntactic uniformity with the other vector ops, and to avoid mistakes: void main() { int[3] a; a[] = 1; assert(a == [1, 1, 1]); } Bye, bearophile
Oct 31 2011
On 10/31/2011 08:34 PM, bearophile wrote:Kenji Hara (and the D community) is really good, he has already written a pull request with the bug fix: https://github.com/D-Programming-Language/dmd/pull/483 --------------------- Kenji Hara has fixed about 1/3 of the issue, so he asked me to split the but report, this is a spin off: http://d.puremagic.com/issues/show_bug.cgi?id=6869 In DMD 2.056 this code compiles: void main() { int[] a1 = [5, 4, 3]; int* p1 = cast(int*)a1; // no compile error here } Similar code using user-created struct doesn't compile: struct Foo { int* p; size_t n; } void main() { Foo f; auto x = cast(int*)f; // compile error here }That is not similar code. This is: struct Foo { size_t length; int* ptr; T opCast(T: int*)(){return ptr;} } void main() { Foo f; auto x = cast(int*)f; // no compile error here }I don't see the need to accept this cast, because we have said that D arrays are not pointers, and allowing the array to pointer cast means introducing/leaving an useless special case, and in practice this special case is not useful because arrays have the ptr property:extern(C) void foo(char* str); foo(cast(char*)"hello");struct Foo { int* p; size_t n; } void main() { Foo f; auto x = f.ptr; // OK }Actually compile error :o).So I think cast(int*)a1 should be forbidden.-1. I don't really see any point in disallowing it. It is an explicit cast, not some kind of bug prone implicit behaviour.----------------------- The third part of the bug report was part of this older one: http://d.puremagic.com/issues/show_bug.cgi?id=3971 The idea is to forbid code like: void main() { int[3] a; a = 1; assert(a == [1, 1, 1]); } And require the square brackets every time an array operation is performed, for syntactic uniformity with the other vector ops, and to avoid mistakes: void main() { int[3] a; a[] = 1; assert(a == [1, 1, 1]); }+1. That helps static type safety a bit and forces code to be more readable.
Oct 31 2011
Timon Gehr:I see. The bug report of mine asks to remove that opCast() then :-)Similar code using user-created struct doesn't compile: struct Foo { int* p; size_t n; } void main() { Foo f; auto x = cast(int*)f; // compile error here }That is not similar code. This is: struct Foo { size_t length; int* ptr; T opCast(T: int*)(){return ptr;} } void main() { Foo f; auto x = cast(int*)f; // no compile error here }extern(C) void foo(char* str); foo(cast(char*)"hello");cast(char*) is D code, it's not a legacy C idiom, so you are writing it now in the D programs. Five years from now do you prefer D programmers to write: extern(C) void puts(const char* str); void main() { puts(cast(char*)"hello"); } Or: extern(C) void puts(const char* str); void main() { puts("hello".ptr); } ? Casts are unsafe and using the ptr is even shorter to write. I don't seen the need of that opCast.-1. I don't really see any point in disallowing it. It is an explicit cast, not some kind of bug prone implicit behaviour.In D there is only one syntax to perform a const cast or reinterpret cast, so D casts are sometimes dangerous: you change something but you forgot to update one cast, the compiler gives you zero warnings because casts are usually silently accepted, and your code breaks. This has happened to me more than one time in D coding. It's much better to minimize their number in the D code (and it's often better to write them in a smart way, with a type taken from what you are working on, like cast(typeof(x)), instead of specifying an explicit type like cast(int)). Sometimes I am not happy even using Unqual!(), I'd like something that performs a more focused job, like a Deconst!() that only removes all the const/immutable from a type, and nothing else. Bye, bearophile
Oct 31 2011
On 11/01/2011 01:38 AM, bearophile wrote:Timon Gehr:That works without the cast.extern(C) void foo(char* str); foo(cast(char*)"hello");cast(char*) is D code, it's not a legacy C idiom, so you are writing it now in the D programs. Five years from now do you prefer D programmers to write: extern(C) void puts(const char* str); void main() { puts(cast(char*)"hello"); }Or: extern(C) void puts(const char* str); void main() { puts("hello".ptr); }That works without the ".ptr".? Casts are unsafe and using the ptr is even shorter to write. I don't seen the need of that opCast.I was casting to char*, not const(char*). It is just that occasionally C headers/bindings lack the const qualifier. Then passing a string literal is achieved simplest by a cast to char*. I don't think we really need that feature, I just think that removing it breaks existing code without a reason. extern(C) void puts(char* str); void main() { puts(cast(char*)"hello"); }
Nov 01 2011
In the meantime Walter has added the patch to the latest DMD. Timon Gehr:That works without the cast. That works without the ".ptr".Right. There is an implict conversion between the 2-word struct of the string to the nude pointer.I was casting to char*, not const(char*). It is just that occasionally C headers/bindings lack the const qualifier. Then passing a string literal is achieved simplest by a cast to char*.In some situations like that I think that using someString.dup.ptr looks safer, or better using toStringz: http://d-programming-language.org/cutting-edge/phobos/std_string.html#toStringz I'd like toStringz to be pure and return a char*, so its result is assignable to immutable despite being fit for C functions without const too. To do this, it can't contain a ~ (string concat) because currently the ~ is not a pure function, it always returns a string, dstring, wstring. So I think this should compile: char[] foo(string s1, string s2) pure { return s1 ~ s2; } void main() {} And regarding toStringz(), this modified version seems to work as desired: import core.stdc.string; char* toStringz(immutable(char[]) s) pure nothrow in { // The assert below contradicts the unittests! //assert(memchr(s.ptr, 0, s.length) == null, //text(s.length, ": `", s, "'")); } out (result) { if (result) { auto slen = s.length; while (slen > 0 && s[slen-1] == 0) --slen; assert(strlen(result) == slen); assert(memcmp(result, s.ptr, slen) == 0); // overkill? } } body { /+ Unfortunately, this isn't reliable. We could make this work if string literals are put in read-only memory and we test if s[] is pointing into that. /* Peek past end of s[], if it's 0, no conversion necessary. * Note that the compiler will put a 0 past the end of static * strings, and the storage allocator will put a 0 past the end * of newly allocated char[]'s. */ char* p = &s[0] + s.length; if (*p == 0) return s; +/ // Need to make a copy auto copy = new char[s.length + 1]; copy[0..s.length] = s; copy[s.length] = 0; return copy.ptr; } void main() { string t = "hello"; char* s1 = toStringz(t); const(char*) s2 = toStringz(t); immutable(char*) s3 = toStringz(t); immutable(char)* s4 = toStringz(t); }I don't think we really need that feature, I just think that removing it breaks existing code without a reason. extern(C) void puts(char* str); void main() { puts(cast(char*)"hello"); }I prefer something like: extern(C) void puts(char* str); void main() { puts(Deconst!("hello".ptr)); } This avoids a cast, a Deconst template doesn't change the data, it never forces the string to be of a specific char type. Thank you for your answers, bearophile
Nov 01 2011
So I think this should compile: char[] foo(string s1, string s2) pure { return s1 ~ s2; } void main() {}The situation is a bit more complex: char[] foo(immutable string s1, immutable string s2) pure { return s1 ~ s2; } void main() { string t1 = "foo"; string t2 = "bar"; auto t3 = t1 ~ t2; static assert(is(typeof(t3) == string)); } So there I was asking for the druntime array concat to return something immutable that is implicitly cast-able to mutable. It's kind of the opposite of the recently introduced rule for strongly pure functions... So I don't know if this is possible.And regarding toStringz(), this modified version seems to work as desired:http://d.puremagic.com/issues/show_bug.cgi?id=6878 Bye, bearophile
Nov 01 2011
Le 31/10/2011 21:25, Timon Gehr a écrit :On 10/31/2011 08:34 PM, bearophile wrote:Well, because the ptr property is done for that. Actually, D ABI says that the struct representing the array begins with length, then prt, so the result isn't obvious from a low level perspective, which is kinda sad when it goes to pointer manipulation.I don't see the need to accept this cast, because we have said that D arrays are not pointers, and allowing the array to pointer cast means introducing/leaving an useless special case, and in practice this special case is not useful because arrays have the ptr property:extern(C) void foo(char* str); foo(cast(char*)"hello");struct Foo { int* p; size_t n; } void main() { Foo f; auto x = f.ptr; // OK }Actually compile error :o).So I think cast(int*)a1 should be forbidden.-1. I don't really see any point in disallowing it. It is an explicit cast, not some kind of bug prone implicit behaviour.
Nov 02 2011
On 02.11.2011 22:19, deadalnix wrote:Le 31/10/2011 21:25, Timon Gehr a écrit :The fix has already been implemented in git master. The bug report is closed. There's no point commenting on this topic further.On 10/31/2011 08:34 PM, bearophile wrote:Well, because the ptr property is done for that. Actually, D ABI says that the struct representing the array begins with length, then prt, so the result isn't obvious from a low level perspective, which is kinda sad when it goes to pointer manipulation.I don't see the need to accept this cast, because we have said that D arrays are not pointers, and allowing the array to pointer cast means introducing/leaving an useless special case, and in practice this special case is not useful because arrays have the ptr property:extern(C) void foo(char* str); foo(cast(char*)"hello");struct Foo { int* p; size_t n; } void main() { Foo f; auto x = f.ptr; // OK }Actually compile error :o).So I think cast(int*)a1 should be forbidden.-1. I don't really see any point in disallowing it. It is an explicit cast, not some kind of bug prone implicit behaviour.
Nov 03 2011
On Monday, 31 October 2011 at 20:26:35 UTC, Timon Gehr wrote:On 10/31/2011 08:34 PM, bearophile wrote:I saw that it was closed today: https://issues.dlang.org/show_bug.cgi?id=6869 Sorry for reviving an old thread. But I have to think that the problem will not be seen in newer versions? Thanks... SDB 79Kenji Hara (and the D community) is really good, he has already written a pull request with the bug fix: https://github.com/D-Programming-Language/dmd/pull/483 --------------------- Kenji Hara has fixed about 1/3 of the issue, so he asked me to split the but report, this is a spin off: http://d.puremagic.com/issues/show_bug.cgi?id=6869 In DMD 2.056 this code compiles: void main() { int[] a1 = [5, 4, 3]; int* p1 = cast(int*)a1; // no compile error here } Similar code using user-created struct doesn't compile: struct Foo { int* p; size_t n; } void main() { Foo f; auto x = cast(int*)f; // compile error here }That is not similar code. This is: struct Foo { size_t length; int* ptr; T opCast(T: int*)(){return ptr;} } void main() { Foo f; auto x = cast(int*)f; // no compile error here }I don't see the need to accept this cast, because we have said that D arrays are not pointers, and allowing the array to pointer cast means introducing/leaving an useless special case, and in practice this special case is not useful because arrays have the ptr property:extern(C) void foo(char* str); foo(cast(char*)"hello");struct Foo { int* p; size_t n; } void main() { Foo f; auto x = f.ptr; // OK }Actually compile error :o).So I think cast(int*)a1 should be forbidden.-1. I don't really see any point in disallowing it. It is an explicit cast, not some kind of bug prone implicit behaviour.----------------------- The third part of the bug report was part of this older one: http://d.puremagic.com/issues/show_bug.cgi?id=3971 The idea is to forbid code like: void main() { int[3] a; a = 1; assert(a == [1, 1, 1]); } And require the square brackets every time an array operation is performed, for syntactic uniformity with the other vector ops, and to avoid mistakes: void main() { int[3] a; a[] = 1; assert(a == [1, 1, 1]); }+1. That helps static type safety a bit and forces code to be more readable.
May 13 2023
On Saturday, 13 May 2023 at 12:55:24 UTC, Salih Dincer wrote:I saw that it was closed today: https://issues.dlang.org/show_bug.cgi?id=6869A new issue has been reported by Steven Schveighoffer: https://issues.dlang.org/show_bug.cgi?id=23919Casting an array to a pointer is allowed: ```d import core.stdc.stdio; auto str = "hello"; printf(cast(char *)str[0 .. 3]); ``` This prints "hello". The user might think they have properly matched the requirements, but in actuality, all they have done is accessed the pointer. A few reasons why this is bad: 1. It's trivial (and more readable) to use `.ptr` instead of the cast 2. The cast must match the attributes or risk causing problems when code evolves. Casting is a blunt instrument, and should be discouraged when better alternatives exist. 3. The cast gives a false impression that something is happening underneath to ensure the data is correct. Many C functions require pointers instead of arrays, and this "seems" like the right answer. I think we should deprecate this "feature". I'm not exactly sure why this was needed in the first place. opening this to hopefully reconsider the decision. FWIW, the D discord has had a few people coming to ask why their code doesn't work when casting a `string` to a `char *`. I would pair such a cast error with a suggestion to use `toStringz` in the case of string to char * conversions.SDB 79
May 13 2023
On Sun, 30 Oct 2011 17:29:36 -0400, bearophile wrote:Do you see the bug I have found during the debugging? I think the D2 compiler has to catch this bug: *array = ...;It is not a bug, it is a feature. If you really do not like it, use the .ptr property. :)
Nov 05 2011
On 05.11.2011 12:35, Dejan Lekic wrote:On Sun, 30 Oct 2011 17:29:36 -0400, bearophile wrote:It was a bug. And it's now been fixed.Do you see the bug I have found during the debugging? I think the D2 compiler has to catch this bug: *array = ...;It is not a bug, it is a feature. If you really do not like it, use the .ptr property. :)
Nov 05 2011
Don wrote:It was a bug. And it's now been fixed.Don, care to explain why? If I want to treat D's array like I would do in C, why not allow me do so?
Nov 07 2011
On 07.11.2011 10:45, Dejan Lekic wrote:Don wrote:I had no involvement with it at all. Although, when we originally banned implicit conversions from arrays to pointers, it was because it was _the_ most common bug in D code. Especially when you pass a char[] array to an extern(C) function that accepts a char *. It really was a disaster. Just add .ptr if you want to convert it to a pointer. It's beautiful, really.It was a bug. And it's now been fixed.Don, care to explain why? If I want to treat D's array like I would do in C, why not allow me do so?
Nov 09 2011