www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - char* pointers between C and D

reply pascal111 <judas.the.messiah.111 gmail.com> writes:
I have small C program that uses a pointer to change the start 
address of a string, and when I tried to do the same code but 
with D, the D code printed the address of the string after I 
increased it one step instead of printing the string the pointer 
pointing to. Is there a difference between "char *" pointers 
between C and D.

#include <stdio.h>
#include <stdlib.h>

int main()
{

     char ch[]="Hello World!";
     char *p;

     p=&ch;
     p++;

     printf("%s\n", p);

     return 0;
}


module main;

import std.stdio;

int main(string[] args)
{

     char[] ch="Hello World!".dup;
     char *p;

     p=&ch[0];
     p++;

     writefln("%s", p);

	return 0;
}
Jul 25 2022
next sibling parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
I don't know what `writefln` is doing, but this following D code 
is the exact similar to your C code

```
import core.stdc.stdio;

void main()
{
     const(char)[] ch = "Hello World!";
     const(char)* p;

     p = &ch[0];
     p++;

     printf("%s", p);
}
```
`ello World!`
Jul 25 2022
parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
Here is the way to do it with `writefln` (i think)


```D
import std;
import core.stdc.string;

void main()
{
     const(char)[] ch = "Hello World!";
     const(char)[] ch2 = "abc";
     const(char)* p;

     p = &ch[0];
     p++;
	
     auto str = p[0 .. strlen(p)];
     writefln("%s", str);
}
```

Note that i removed your `.dup` it is unecessary, string literals 
needs `const(char)`

After looking at the doc, `writefln` needs a slice, so we just do 
that and pass it
Jul 25 2022
parent reply pascal111 <judas.the.messiah.111 gmail.com> writes:
On Monday, 25 July 2022 at 09:36:05 UTC, ryuukk_ wrote:
 Here is the way to do it with `writefln` (i think)


 ```D
 import std;
 import core.stdc.string;

 void main()
 {
     const(char)[] ch = "Hello World!";
     const(char)[] ch2 = "abc";
     const(char)* p;

     p = &ch[0];
     p++;
 	
     auto str = p[0 .. strlen(p)];
     writefln("%s", str);
 }
 ```

 Note that i removed your `.dup` it is unecessary, string 
 literals needs `const(char)`

 After looking at the doc, `writefln` needs a slice, so we just 
 do that and pass it
I tried your advice with two ways; once with a constant and other with an array, but the result isn't the same. The array case has more letters in the output. module main; import std.stdio; import core.stdc.stdio; import core.stdc.string; int main(string[] args) { const(char)[] ch1 = "Hello World!"; char[] ch2="Hello World!".dup; const(char) *p1; char *p2; p1=ch1.ptr; p2=ch2.ptr; writeln(p1[0..strlen(p1)]); writeln(p2[0..strlen(p2)]); return 0; } Runtime output: https://i.postimg.cc/sfnkJ4GM/Screenshot-from-2022-07-25-13-12-03.png
Jul 25 2022
next sibling parent ag0aep6g <anonymous example.com> writes:
On Monday, 25 July 2022 at 11:14:56 UTC, pascal111 wrote:
 module main;

 import std.stdio;
 import core.stdc.stdio;
 import core.stdc.string;

 int main(string[] args)
 {


         const(char)[] ch1 = "Hello World!";
         char[] ch2="Hello World!".dup;

         const(char) *p1;
         char *p2;

         p1=ch1.ptr;
         p2=ch2.ptr;

         writeln(p1[0..strlen(p1)]);
         writeln(p2[0..strlen(p2)]);

     	return 0;
     }


 Runtime output:

 https://i.postimg.cc/sfnkJ4GM/Screenshot-from-2022-07-25-13-12-03.png
Do not post screenshots of text. `strlen` only works on null-terminated strings. The result of `.dup` is not null-terminated, so `strlen` doesn't work on it.
Jul 25 2022
prev sibling next sibling parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
On Monday, 25 July 2022 at 11:14:56 UTC, pascal111 wrote:
 On Monday, 25 July 2022 at 09:36:05 UTC, ryuukk_ wrote:
 Here is the way to do it with `writefln` (i think)


 ```D
 import std;
 import core.stdc.string;

 void main()
 {
     const(char)[] ch = "Hello World!";
     const(char)[] ch2 = "abc";
     const(char)* p;

     p = &ch[0];
     p++;
 	
     auto str = p[0 .. strlen(p)];
     writefln("%s", str);
 }
 ```

 Note that i removed your `.dup` it is unecessary, string 
 literals needs `const(char)`

 After looking at the doc, `writefln` needs a slice, so we just 
 do that and pass it
I tried your advice with two ways; once with a constant and other with an array, but the result isn't the same. The array case has more letters in the output. module main; import std.stdio; import core.stdc.stdio; import core.stdc.string; int main(string[] args) { const(char)[] ch1 = "Hello World!"; char[] ch2="Hello World!".dup; const(char) *p1; char *p2; p1=ch1.ptr; p2=ch2.ptr; writeln(p1[0..strlen(p1)]); writeln(p2[0..strlen(p2)]); return 0; } Runtime output: https://i.postimg.cc/sfnkJ4GM/Screenshot-from-2022-07-25-13-12-03.png
`ch1`is a string literal, just like in C, it is null terminated `ch2` is a GC allocated char array, it is NOT null terminated `strlen` is the lib C function, it counts strings up to `\O` for `p1` it'll print correctly, it is a pointer from the null terminated string for `p2` strlen doesn't make sense, since it is a pointer from a string that is NOT null terminated
Jul 25 2022
next sibling parent reply pascal111 <judas.the.messiah.111 gmail.com> writes:
On Monday, 25 July 2022 at 13:51:35 UTC, ryuukk_ wrote:
 On Monday, 25 July 2022 at 11:14:56 UTC, pascal111 wrote:
 On Monday, 25 July 2022 at 09:36:05 UTC, ryuukk_ wrote:
 [...]
I tried your advice with two ways; once with a constant and other with an array, but the result isn't the same. The array case has more letters in the output. module main; import std.stdio; import core.stdc.stdio; import core.stdc.string; int main(string[] args) { const(char)[] ch1 = "Hello World!"; char[] ch2="Hello World!".dup; const(char) *p1; char *p2; p1=ch1.ptr; p2=ch2.ptr; writeln(p1[0..strlen(p1)]); writeln(p2[0..strlen(p2)]); return 0; } Runtime output: https://i.postimg.cc/sfnkJ4GM/Screenshot-from-2022-07-25-13-12-03.png
`ch1`is a string literal, just like in C, it is null terminated `ch2` is a GC allocated char array, it is NOT null terminated `strlen` is the lib C function, it counts strings up to `\O` for `p1` it'll print correctly, it is a pointer from the null terminated string for `p2` strlen doesn't make sense, since it is a pointer from a string that is NOT null terminated
Yes, I have to add "\0": module main; import std.stdio; import core.stdc.stdio; import core.stdc.string; int main(string[] args) { const(char)[] ch1 = "Hello World!"; char[] ch2="Hello World!".dup; const(char) *p1; char *p2; ch2~="\0"; p1=ch1.ptr; p2=ch2.ptr; writeln(p1[0..strlen(p1)]); writeln(p2[0..strlen(p2)]); return 0; }
Jul 25 2022
parent "H. S. Teoh" <hsteoh qfbox.info> writes:
On Mon, Jul 25, 2022 at 05:30:14PM +0000, pascal111 via Digitalmars-d-learn
wrote:
[...]
 int main(string[] args)
 {
 
 
         const(char)[] ch1 = "Hello World!";
         char[] ch2="Hello World!".dup;
 
         const(char) *p1;
         char *p2;
 
         ch2~="\0";
 
         p1=ch1.ptr;
         p2=ch2.ptr;
 
         writeln(p1[0..strlen(p1)]);
         writeln(p2[0..strlen(p2)]);
Unless you are passing the string back to C code as char*, there is no need to use strlen here. You can just use `writeln(p1);` to output the entire string, or slice it with `p1[0 .. $]` to get the entire string. T -- Being able to learn is a great learning; being able to unlearn is a greater learning.
Jul 25 2022
prev sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 7/25/22 06:51, ryuukk_ wrote:
 On Monday, 25 July 2022 at 11:14:56 UTC, pascal111 wrote:
         const(char)[] ch1 = "Hello World!";
         char[] ch2="Hello World!".dup;
[...]
 `ch1`is a string literal, just like in C, it is null terminated
To be pedantic, ch1 is not the string literal but a slice of it. "Hello world" is the string literal and does have a '\0' at the end.
 `ch2` is a GC allocated char array, it is NOT null terminated
Yes. The only difference between ch1 and ch2 is that ch1 does not incur an allocation cost. Ali
Aug 09 2022
prev sibling parent Kagamin <spam here.lot> writes:
This is how to do it the D way:
```
int main(string[] args)
{
	string ch1 = "Hello World!";
	char[] ch2="Hello World!".dup;

	string s1=ch1[1..$];
	char[] s2=ch2[1..$];

	writeln(s1);
	writeln(s2);

	return 0;
}
```
Jul 25 2022
prev sibling parent Mike Parker <aldacron gmail.com> writes:
On Monday, 25 July 2022 at 09:04:29 UTC, pascal111 wrote:
 I have small C program that uses a pointer to change the start 
 address of a string, and when I tried to do the same code but 
 with D, the D code printed the address of the string after I 
 increased it one step instead of printing the string the 
 pointer pointing to. Is there a difference between "char *" 
 pointers between C and D.
No, no difference. Pointers are the same in both languages. What's different is the behavior of `%s` in `writeln` vs `printf`. See the documentation on format strings at: https://dlang.org/phobos/std_format.html Essentially, `%s` tells the formatter to output something appropriate for the given type. For an actual D string, you see the text. For an integral or floating point type, you see the number. For a pointer, you see the the address. And so on. Do in your case, to get `writefln` to print the text instead of the pointer address, you could import `std.string` and use `fromStringz`:`fromStringz(p)`. This will give you a D string without allocating any memory. Basically an immutable slice of the memory pointed at by `p`. That's fine for this use case, but if you wanted to hang on to the string beyond the lifetime of the pointer, you'd have to use `std.conv.to` instead (e.g., `to!string(p)`).
Jul 25 2022