How to use core.vararg to print D variadic arguments and their types without using ! (template instantiation)?
https://dlang.org/phobos/core_vararg.html The common way to use **va_arg** is `va_arg!(int)(_argptr);` What would be the alternative way or syntax that behave exactly the same way, even if more verbose? `va_arg!(int)(_argptr);` is taken from an example in: https://dlang.org/spec/function.html#d_style_variadic_functions
Re: Help on array pointers
On Thursday, 14 September 2023 at 14:21:09 UTC, Vino wrote: Questions:1 ``` char[] invalid = (cast(char*)malloc(char.sizeof * length))[0..length]; ``` The above statement allocate memory for char type and the size of the allocated memory is char.sizeof * length so what is the use of this "[0..length]"; The difference between a `char*` and a `char[]` is that the `char[]` includes both the pointer and the length in the same variable. The slicing operator `[0 .. length]` is used to combine the pointer and the length into a single `char[]` variable. Strictly speaking, you don't *have* to do this--you could leave the pointer and the length in separate variables, and the program would still work. Most D programmers prefer to combine them because it's more convenient and less error-prone (for example, it makes it much harder to accidentally use the wrong length). Question:2 ``` char[]* invalidptr = &invalid; ``` Is this the right way to create a array pointer. It depends on what you mean by "array pointer". A `char[]` contains a pointer and a length. A `char[]*` is a pointer to a thing that contains a pointer and a length. In order to get from a `char[]*` to the actual `char` data, you have to follow *two* pointers. In that sense, you can think of `char[]*` in D as similar to `char**` in C. Question: 3 ``` ST1: char[] invalid = (cast(char*)malloc(char.sizeof * length))[0..length]; ST2: char[]* invalid = (cast(char*)malloc(char.sizeof * length))[0..length]; ``` What is the difference between the above to statement. The first statement is valid code and the second one isn't. Question: 4 Who do we free the memory allocated. Code: [...] In order to ensure that the memory is freed correctly even when an exception is thrown, you can use a [`try`/`finally` block.][1] char[] a = (cast(char*) malloc(char.sizeof * length))[0 .. length]; try { doSomethingWith(a); } finally { free(a.ptr); } However, this by itself will not fix the code in your example because it has another serious mistake: it does not initialize the memory allocated by `malloc`. Attempting to read from uninitialized memory results in [undefined behavior][2], which may cause your program to crash or behave unpredictably. [1]: http://ddili.org/ders/d.en/exceptions.html#ix_exceptions.try [2]: https://c-faq.com/ansi/undef.html
Re: Help on array pointers
On Thursday, 14 September 2023 at 15:33:45 UTC, Paul Backus wrote: On Thursday, 14 September 2023 at 14:21:09 UTC, Vino wrote: Questions:1 ``` char[] invalid = (cast(char*)malloc(char.sizeof * length))[0..length]; ``` The above statement allocate memory for char type and the size of the allocated memory is char.sizeof * length so what is the use of this "[0..length]"; The difference between a `char*` and a `char[]` is that the `char[]` includes both the pointer and the length in the same variable. The slicing operator `[0 .. length]` is used to combine the pointer and the length into a single `char[]` variable. Strictly speaking, you don't *have* to do this--you could leave the pointer and the length in separate variables, and the program would still work. Most D programmers prefer to combine them because it's more convenient and less error-prone (for example, it makes it much harder to accidentally use the wrong length). Question:2 ``` char[]* invalidptr = &invalid; ``` Is this the right way to create a array pointer. It depends on what you mean by "array pointer". A `char[]` contains a pointer and a length. A `char[]*` is a pointer to a thing that contains a pointer and a length. In order to get from a `char[]*` to the actual `char` data, you have to follow *two* pointers. In that sense, you can think of `char[]*` in D as similar to `char**` in C. Question: 3 ``` ST1: char[] invalid = (cast(char*)malloc(char.sizeof * length))[0..length]; ST2: char[]* invalid = (cast(char*)malloc(char.sizeof * length))[0..length]; ``` What is the difference between the above to statement. The first statement is valid code and the second one isn't. Question: 4 Who do we free the memory allocated. Code: [...] In order to ensure that the memory is freed correctly even when an exception is thrown, you can use a [`try`/`finally` block.][1] char[] a = (cast(char*) malloc(char.sizeof * length))[0 .. length]; try { doSomethingWith(a); } finally { free(a.ptr); } However, this by itself will not fix the code in your example because it has another serious mistake: it does not initialize the memory allocated by `malloc`. Attempting to read from uninitialized memory results in [undefined behavior][2], which may cause your program to crash or behave unpredictably. [1]: http://ddili.org/ders/d.en/exceptions.html#ix_exceptions.try [2]: https://c-faq.com/ansi/undef.html Hi Pual, Thank you very much for the explanation, based on your statement i modifiyed the code as below, and now ti dose not throw the exception where it should throw exception Code: ``` import std.stdio: writeln; import std.exception: enforce; import std.range: empty; import std.format: format; auto ref testNames(in string[] names) { enforce(!empty(names), "Names cannot be Empty or Null"); import core.stdc.stdlib; import std.algorithm: any, canFind; string[] _names; size_t length = 20; char[] invalid = (cast(char*)malloc(char.sizeof * length))[0..length]; invalid[0 ..length] = 0; try { version(Windows) { invalid = ['\'','\"',':',';','*','&','[',']','-','+','$','#','<','>','{','}','(',')']; } foreach(i; names.dup) { auto result = i.any!(a => invalid.canFind(a)); if(result) { throw new Exception("Invalid Name passed: %s".format(i)); } } } catch(Exception e) { writeln(e.msg); } finally { free(invalid.ptr); } _names = names.dup; return _names; } void main () { writeln(testNames(["/T&name"])); } ```
Re: Help on array pointers
On Thursday, 14 September 2023 at 17:23:53 UTC, Vino wrote: On Thursday, 14 September 2023 at 15:33:45 UTC, Paul Backus wrote: On Thursday, 14 September 2023 at 14:21:09 UTC, Vino wrote: Questions:1 ``` char[] invalid = (cast(char*)malloc(char.sizeof * length))[0..length]; ``` The above statement allocate memory for char type and the size of the allocated memory is char.sizeof * length so what is the use of this "[0..length]"; The difference between a `char*` and a `char[]` is that the `char[]` includes both the pointer and the length in the same variable. The slicing operator `[0 .. length]` is used to combine the pointer and the length into a single `char[]` variable. Strictly speaking, you don't *have* to do this--you could leave the pointer and the length in separate variables, and the program would still work. Most D programmers prefer to combine them because it's more convenient and less error-prone (for example, it makes it much harder to accidentally use the wrong length). Question:2 ``` char[]* invalidptr = &invalid; ``` Is this the right way to create a array pointer. It depends on what you mean by "array pointer". A `char[]` contains a pointer and a length. A `char[]*` is a pointer to a thing that contains a pointer and a length. In order to get from a `char[]*` to the actual `char` data, you have to follow *two* pointers. In that sense, you can think of `char[]*` in D as similar to `char**` in C. Question: 3 ``` ST1: char[] invalid = (cast(char*)malloc(char.sizeof * length))[0..length]; ST2: char[]* invalid = (cast(char*)malloc(char.sizeof * length))[0..length]; ``` What is the difference between the above to statement. The first statement is valid code and the second one isn't. Question: 4 Who do we free the memory allocated. Code: [...] In order to ensure that the memory is freed correctly even when an exception is thrown, you can use a [`try`/`finally` block.][1] char[] a = (cast(char*) malloc(char.sizeof * length))[0 .. length]; try { doSomethingWith(a); } finally { free(a.ptr); } However, this by itself will not fix the code in your example because it has another serious mistake: it does not initialize the memory allocated by `malloc`. Attempting to read from uninitialized memory results in [undefined behavior][2], which may cause your program to crash or behave unpredictably. [1]: http://ddili.org/ders/d.en/exceptions.html#ix_exceptions.try [2]: https://c-faq.com/ansi/undef.html Hi Pual, Thank you very much for the explanation, based on your statement i modifiyed the code as below, and now ti dose not throw the exception where it should throw exception Code: ``` import std.stdio: writeln; import std.exception: enforce; import std.range: empty; import std.format: format; auto ref testNames(in string[] names) { enforce(!empty(names), "Names cannot be Empty or Null"); import core.stdc.stdlib; import std.algorithm: any, canFind; string[] _names; size_t length = 20; char[] invalid = (cast(char*)malloc(char.sizeof * length))[0..length]; invalid[0 ..length] = 0; try { version(Windows) { invalid = ['\'','\"',':',';','*','&','[',']','-','+','$','#','<','>','{','}','(',')']; } foreach(i; names.dup) { auto result = i.any!(a => invalid.canFind(a)); if(result) { throw new Exception("Invalid Name passed: %s".format(i)); } } } catch(Exception e) { writeln(e.msg); } finally { free(invalid.ptr); } _names = names.dup; return _names; } void main () { writeln(testNames(["/T&name"])); } ``` Hi All, Was able to find out the issue, and now it is throwing both the exception and another error message as below https://run.dlang.io/is/VZeOOj Error: ``` Invalid Name passed: /T&name double free or corruption (out) Error: program killed by signal 6 ``` Code: ``` import std.stdio: writeln; import std.exception: enforce; import std.range: empty; import std.format: format; auto ref testNames(in string[] names) { enforce(!empty(names), "Names cannot be Empty or Null"); import core.stdc.stdlib; import std.algorithm: any, canFind; string[] _names; size_t length = 20; char[] invalid = (cast(char*)malloc(char.sizeof * length))[0..length]; invalid[0 ..length] = 0; try { invalid = ['\'','\"',':',';','*','&','[',']','-','+','$','#','<','>','{','}','(',')']; foreach(i; names.dup) { auto result = i.any!(a => invalid.canFind(a)); if(result) { throw new Exception("Invalid Na
Re: Help on array pointers
On Thursday, 14 September 2023 at 14:21:09 UTC, Vino wrote: Hi All, Request your help to guide me in understanding about pointers, the below code works,I have few question which i need your help for better understanding. Questions:1 ``` char[] invalid = (cast(char*)malloc(char.sizeof * length))[0..length]; ``` The above statement allocate memory for char type and the size of the allocated memory is char.sizeof * length so what is the use of this "[0..length]"; Question:2 ``` char[]* invalidptr = &invalid; ``` Is this the right way to create a array pointer. Question: 3 ``` ST1: char[] invalid = (cast(char*)malloc(char.sizeof * length))[0..length]; ST2: char[]* invalid = (cast(char*)malloc(char.sizeof * length))[0..length]; ``` What is the difference between the above to statement. Question: 4 Who do we free the memory allocated. Code: ``` auto ref testNames(in string[] names) { enforce(!empty(names), "Names cannot be Empty or Null"); import core.stdc.stdlib; import std.algorithm: any, canFind; size_t length = 20; char[] invalid = (cast(char*)malloc(char.sizeof * length))[0..length]; char[]* invalidptr = &invalid; version(Windows) { (*invalidptr) = ['\'','\"',':',';','*','&','[',']','-','+','$','#','<','>','{','}','(',')']; } foreach(i; names.dup) { auto result = i.any!(a => (*invalidptr).canFind(a)); if(result) { throw new Exception("Invalid Name passed: %s".format(i)); } } string[] _names = names.dup; return _names; } ``` From, Vino A pointer is a type that points to something. It's literally that simple. Every piece of data and code exist somewhere in memory. Every piece of memory has an address. The address is what a pointer contains. Sometimes we want a type that is the address itself rather than a value/number. https://run.dlang.io/gist/19c63d325ee412df23bdbefabce111b9 import std, std.stdio, core.stdc.stdlib; void main() { float x = 43.534f; // Creates a float type that hold sthe value 43.534 writeln("Value of x = ", x); // Displays it's value writeln("Address of x = ", &x); // Displays it's address writeln(); float* y = null; // creates a pointer of type float note that it is point to no memory location(null) and so it is an error to store a value to the location writeln("Value of y = ", y); // Displays it's address(remember, y is a ptr to a float, not a float) y = new float(); // This allocates free/unused memory(of float type) to y so we can store a value. *y = 50.34f; // assigns it the value 50.34. We have to use * because if we didn't we would be trying to change the address of y writeln("Value of y = ", y); // Displays it's address(remember, y is a ptr to a float, not a float) writeln("Address of y = ", &y); // Writes it's address(y is a pointer but it also is stored in a location in memory and hence has an address writeln("Dereferenced value of y = ", *y); // Displays the value y is pointing to interpreting it as a float(the base type of the pointer) writeln("Dereferences the value of y as if it were an int = ", *(cast(int*)y)); // Displays the value y is pointing to interpreting it as a int. We have to force the compilier to reinterpret it as an int*. writeln(); byte[] z; // Creates an array of bytes. That is, the compiler will create a pointer to an array of memory and track it's length and deal with memory allocation and all that. writeln("Value of z = ", z); // Displays it's address(remember, z is a ptr to a float, not a float) writeln("Address of z = ", &z); // Note that z is an array but it is a pointer to and &z gets the address where the "array" is stored. writeln("Value of z's pointer = ", z.ptr); // Displays it's address(remember, y is a ptr to a float, not a float) writeln("Length of z = ", z.length); // Writes it's address(y is a pointer but it also is stored in a location in memory and hence has an address writeln(); z ~= 4; // We can store/append a value to our array. The compiler will take care of dealing with allocating memory and all that. writeln("Value of z = ", z); // Displays it's address(remember, z is a ptr to a float, not a float) writeln("Address of z = ", &z); // Note that z is an array but it is a pointer to and &z gets the address where the "array" is stored. writeln("Value of z's pointer = ", z.ptr); // Displays it's address(remember, y is a ptr to a float, not a float) writeln("Length of z = ", z.length); // Writes it's address(y is a pointer but it also is stored in a location in memory and hence has an address z ~= 54; // We can store/append a value to our a