digitalmars.D.learn - Using "strcpy" to assign value to dynamic char array
- pascal111 (21/21) Nov 01 2021 I know that I can use the next syntax to assign new value to char
- Steven Schveighoffer (6/24) Nov 01 2021 Don't do this, you just corrupted memory! You wrote 13 bytes into a
- pascal111 (4/28) Nov 01 2021 Yes, I'm practicing doing things in low level style like standard
- =?UTF-8?Q?Ali_=c3=87ehreli?= (14/15) Nov 01 2021 All you needed extra was to let the slice know about the new length:
- pascal111 (4/21) Nov 01 2021 This can serve the style I want. It uses OOP style like C++ by
- =?UTF-8?Q?Ali_=c3=87ehreli?= (13/17) Nov 01 2021 I am feeling funny right now and showing incorrect code. It's impossible...
- pascal111 (2/21) Nov 01 2021 Anyway, I'm a beginner and any information is useful to me.
- =?UTF-8?Q?Ali_=c3=87ehreli?= (21/22) Nov 01 2021 I wrote a cool function to make it easy to disregard memory safety:
- pascal111 (3/26) Nov 01 2021 This function seems smart and flexible and higher than my current
- Steven Schveighoffer (12/17) Nov 02 2021 Please please, do NOT study this code. It is bad all around. Ali should
- pascal111 (4/21) Nov 03 2021 I started to change my mind about doing things in low level of
- Imperatorn (2/27) Nov 03 2021 Good, you will be much happier ☀️
- tsbockman (15/18) Nov 02 2021 The nested struct is not needed. UFCS works for setters, too:
- =?UTF-8?Q?Ali_=c3=87ehreli?= (3/4) Nov 03 2021 Oh yeah! Pretty cool. :)
- jfondren (61/71) Nov 03 2021 Easy win: use normal operations with static arrays instead of
- pascal111 (5/16) Nov 04 2021 .
I know that I can use the next syntax to assign new value to char dynamic array, and the new value isn't in same length of the current value of the array: { char[] s="xyz".dup; s="Hello World!".dup; writeln(s); } Result: Hello World! ===================== But what if I want to use "strcpy" function to assign that new value to the array that the problem is that the array won't take more than its first initializing value length: { char[] s="xyz".dup; strcpy(&s[0], "Hello World!"); writeln(s); } Result: Hel
Nov 01 2021
On 11/1/21 3:56 PM, pascal111 wrote:But what if I want to use "strcpy" function to assign that new value to the array that the problem is that the array won't take more than its first initializing value length: { char[] s="xyz".dup; strcpy(&s[0], "Hello World!"); writeln(s); } Result: HelDon't do this, you just corrupted memory! You wrote 13 bytes into a memory location that contains 3. Use `.dup`, it does the equivalent of `strcpy`. Can you share why you want to use `strcpy` here? -Steve
Nov 01 2021
On Monday, 1 November 2021 at 20:15:14 UTC, Steven Schveighoffer wrote:On 11/1/21 3:56 PM, pascal111 wrote:Yes, I'm practicing doing things in low level style like standard C.But what if I want to use "strcpy" function to assign that new value to the array that the problem is that the array won't take more than its first initializing value length: { char[] s="xyz".dup; strcpy(&s[0], "Hello World!"); writeln(s); } Result: HelDon't do this, you just corrupted memory! You wrote 13 bytes into a memory location that contains 3. Use `.dup`, it does the equivalent of `strcpy`. Can you share why you want to use `strcpy` here? -Steve
Nov 01 2021
On 11/1/21 1:49 PM, pascal111 wrote:Yes, I'm practicing doing things in low level style like standard C.All you needed extra was to let the slice know about the new length: import std.stdio; import core.stdc.string; void main() { char[] s="xyz".dup; strcpy(&s[0], "Hello World!"); s = s.ptr[0..12]; // <-- Here writeln(s); } Now, the result is "correct" without dup: Hello World! The program is as incorrect as its C equivalent would be. ;) Ali
Nov 01 2021
On Monday, 1 November 2021 at 21:01:31 UTC, Ali Çehreli wrote:On 11/1/21 1:49 PM, pascal111 wrote:This can serve the style I want. It uses OOP style like C++ by putting a pointer as a property, but pointers themselves are low level.Yes, I'm practicing doing things in low level style likestandard C. All you needed extra was to let the slice know about the new length: import std.stdio; import core.stdc.string; void main() { char[] s="xyz".dup; strcpy(&s[0], "Hello World!"); s = s.ptr[0..12]; // <-- Here writeln(s); } Now, the result is "correct" without dup: Hello World! The program is as incorrect as its C equivalent would be. ;) Ali
Nov 01 2021
On 11/1/21 2:28 PM, pascal111 wrote:This can serve the style I want.I am feeling funny right now and showing incorrect code. It's impossible to fit "Hello World!" in "xyz". As Steve said, don't do that. :)It uses OOP style like C++ by putting a pointer as a property,D's slices are the equivalent of the following struct (showing for int): struct __Slice__ { size_t length; int * ptr; } So, .ptr is simply a member variable. (Assigning to .length does some magic like allocating more memory in some cases; otherwise it is a member variable as well.)but pointers themselves are low level.arr.ptr is as low as it gets: It is a pointer. Ali
Nov 01 2021
On Monday, 1 November 2021 at 21:37:59 UTC, Ali Çehreli wrote:On 11/1/21 2:28 PM, pascal111 wrote:Anyway, I'm a beginner and any information is useful to me.This can serve the style I want.I am feeling funny right now and showing incorrect code. It's impossible to fit "Hello World!" in "xyz". As Steve said, don't do that. :)It uses OOP style like C++ by putting a pointer as a property,D's slices are the equivalent of the following struct (showing for int): struct __Slice__ { size_t length; int * ptr; } So, .ptr is simply a member variable. (Assigning to .length does some magic like allocating more memory in some cases; otherwise it is a member variable as well.)but pointers themselves are low level.arr.ptr is as low as it gets: It is a pointer. Ali
Nov 01 2021
On 11/1/21 2:01 PM, Ali =C3=87ehreli wrote:The program is as incorrect as its C equivalent would be. ;)I wrote a cool function to make it easy to disregard memory safety: import std.stdio; auto assumedLength(S)(ref S slice) { struct LengthSetter { void opAssign(size_t length) { // Nooo! :) *cast(size_t*)(&slice) =3D length; } } return LengthSetter(); } void main() { auto arr =3D [ 1, 2, 3 ]; arr.assumedLength =3D 10; writeln(arr); } Joking aside, I liked the nested struct and its opAssign to mimic=20 internal `arr.length =3D 42` syntax. (I know it involves a potentially=20 expensive delegate but still...) Ali
Nov 01 2021
On Monday, 1 November 2021 at 21:32:21 UTC, Ali Çehreli wrote:On 11/1/21 2:01 PM, Ali Çehreli wrote:This function seems smart and flexible and higher than my current level, I'll study it.The program is as incorrect as its C equivalent would be. ;)I wrote a cool function to make it easy to disregard memory safety: import std.stdio; auto assumedLength(S)(ref S slice) { struct LengthSetter { void opAssign(size_t length) { // Nooo! :) *cast(size_t*)(&slice) = length; } } return LengthSetter(); } void main() { auto arr = [ 1, 2, 3 ]; arr.assumedLength = 10; writeln(arr); } Joking aside, I liked the nested struct and its opAssign to mimic internal `arr.length = 42` syntax. (I know it involves a potentially expensive delegate but still...) Ali
Nov 01 2021
On 11/1/21 9:03 PM, pascal111 wrote:On Monday, 1 November 2021 at 21:32:21 UTC, Ali Çehreli wrote:...Joking asideThis function seems smart and flexible and higher than my current level, I'll study it.Please please, do NOT study this code. It is bad all around. Ali should know better ;) He is joking with the code posted, it should not be used in any real code ever. Not only is it corrupting memory, it may not work as expected in all cases (and will randomly fail). Please learn first how memory works before writing the low-level bits of arrays! As a beginner, I suggest studying what a buffer overrun is, and why it is bad. -Steve
Nov 02 2021
On Wednesday, 3 November 2021 at 02:38:56 UTC, Steven Schveighoffer wrote:On 11/1/21 9:03 PM, pascal111 wrote:I started to change my mind about doing things in low level of classic C, I started to think get benefits of new features of D.On Monday, 1 November 2021 at 21:32:21 UTC, Ali Çehreli wrote:...Joking asideThis function seems smart and flexible and higher than my current level, I'll study it.Please please, do NOT study this code. It is bad all around. Ali should know better ;) He is joking with the code posted, it should not be used in any real code ever. Not only is it corrupting memory, it may not work as expected in all cases (and will randomly fail). Please learn first how memory works before writing the low-level bits of arrays! As a beginner, I suggest studying what a buffer overrun is, and why it is bad. -Steve
Nov 03 2021
On Wednesday, 3 November 2021 at 10:38:45 UTC, pascal111 wrote:On Wednesday, 3 November 2021 at 02:38:56 UTC, Steven Schveighoffer wrote:Good, you will be much happier ☀️On 11/1/21 9:03 PM, pascal111 wrote:I started to change my mind about doing things in low level of classic C, I started to think get benefits of new features of D.[...]...[...][...]Please please, do NOT study this code. It is bad all around. Ali should know better ;) He is joking with the code posted, it should not be used in any real code ever. Not only is it corrupting memory, it may not work as expected in all cases (and will randomly fail). Please learn first how memory works before writing the low-level bits of arrays! As a beginner, I suggest studying what a buffer overrun is, and why it is bad. -Steve
Nov 03 2021
On Monday, 1 November 2021 at 21:32:21 UTC, Ali Çehreli wrote:Joking aside, I liked the nested struct and its opAssign to mimic internal `arr.length = 42` syntax. (I know it involves a potentially expensive delegate but still...)The nested struct is not needed. UFCS works for setters, too: ```D void assumedLength(S)(ref S slice, size_t length) { if(slice.length >= length) slice.length = length; else assert(false, "Let's not corrupt memory today."); } void main() { auto arr = [ 1, 2, 3 ]; arr.assumedLength = 2; writeln(arr); } ```
Nov 02 2021
On 11/2/21 9:06 PM, tsbockman wrote:UFCS works for setters, too:Oh yeah! Pretty cool. :) Ali
Nov 03 2021
On Monday, 1 November 2021 at 19:56:13 UTC, pascal111 wrote:But what if I want to use "strcpy" function to assign that new value to the array that the problem is that the array won't take more than its first initializing value length: { char[] s="xyz".dup; strcpy(&s[0], "Hello World!"); writeln(s); } Result: HelEasy win: use normal operations with static arrays instead of strcpy: ```d unittest { char[3] s = "xyz"; s = "Hello World"; // Error: index [11] exceeds array of length 3 } ``` Now you'll get errors (in range-checked builds) instead of silent bad behavior. With a larger buffer, short assigns (only with string literals) zero the rest of the buffer: ```d unittest { char[15] s = "xyz"; s = "Hello World"; // this is OK assert(s == "Hello World\0\0\0\0"); } unittest { char[15] s = "Hello World"; s = "xyz"; // so is this assert(s[0 .. 5] == "xyz\0\0"); } ``` But more realistically you'll be getting strings from somewhere and can assign a specific region using the length of those strings: ```d unittest { // pretend these are user inputs string ex1 = "Hello World"; string ex2 = "xyz"; char[15] s; s[0 .. ex1.length] = ex1; assert(s == "Hello World\xFF\xFF\xFF\xFF"); s[0 .. ex2.length] = ex2; assert(s[0 .. ex1.length] == "xyzlo World"); } ``` This is all obviously much more of a hassle than normal D string-handling, but if you're going to apply C levels of care with memory and string handling, you can do that in D while still avoiding C levels of bugs. ```d unittest { import std.algorithm : min; import core.stdc.string : strlen; char[6] buf; string output; foreach (input; ["ok", "Way too long!"]) { auto len = min(buf.length-1, input.length); buf[0 .. len] = input[0 .. len]; buf[len] = '\0'; output ~= buf[0 .. len+1]; } assert(output == "ok\0Way t\0"); assert(output[0 .. strlen(&output[0])] == "ok"); } ```
Nov 03 2021
On Thursday, 4 November 2021 at 01:29:57 UTC, jfondren wrote:On Monday, 1 November 2021 at 19:56:13 UTC, pascal111 wrote:. . .But what if I want to use "strcpy" function to assign that new value to the array that the problem is that the array won't take more than its first initializing value length: {assert(output == "ok\0Way t\0"); assert(output[0 .. strlen(&output[0])] == "ok"); } ```I appreciate your vary explanation.
Nov 04 2021