Help on array pointers

Vino akashvino79 at gmail.com
Thu Sep 14 17:23:53 UTC 2023


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"]));
}
```



More information about the Digitalmars-d-learn mailing list