How to use core.vararg to print D variadic arguments and their types without using ! (template instantiation)?

2023-09-14 Thread BoQsc via Digitalmars-d-learn

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

2023-09-14 Thread Paul Backus via Digitalmars-d-learn

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

2023-09-14 Thread Vino via Digitalmars-d-learn

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

2023-09-14 Thread vino via Digitalmars-d-learn

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

2023-09-14 Thread Joe--- via Digitalmars-d-learn

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