Which of the 2 methods is theoretically faster and why ? (The pointer to string must be constant.)
What is the exact difference between destination[count] and *destination++ ? Does destination[count] keep moving from 0 to count on every call ? Does *destination++ just add 1 on each call ?
char *const string = "Hello world!";
char *destination = malloc(strlen(string) + 1);
int count = 0;
while(string[count] != '\0')
{
destination[count] = string[count];
count++;
}
char *const string = "Hello world!";
char *destination = malloc(strlen(string) + 1);
char *ptr = string;
while(*ptr != '\0')
{
*destination++ = *ptr++;
}
Essentially, there is no difference between string and String (capital S) in C#. String (capital S) is a class in the . NET framework in the System namespace. The fully qualified name is System.
You should not use == (equality operator) to compare these strings because they compare the reference of the string, i.e. whether they are the same object or not. On the other hand, equals() method compares whether the value of the strings is equal, and not the object itself.
We can use == operators for reference comparison (address comparison) and . equals() method for content comparison. In simple words, == checks if both objects point to the same memory location whereas . equals() evaluates to the comparison of values in the objects.
By new keyword : Java String is created by using a keyword “new”. For example: String s=new String(“Welcome”); It creates two objects (in String pool and in heap) and one reference variable where the variable 's' will refer to the object in the heap.
It depends on the compiler. With modern compilers it's really not possible to predict anything about optimization on the single-instruction level without actually looking at the generated code. Both probably compile to equivalent instructions.
That said, destination[count]
does not loop from 0 to count
on each call. It takes the memory location of destination[0]
, adds count
times the size of the type of *destination
, and looks there. (This is all naively speaking, of course - the compiler probably does something faster.)
On the other hand, *destination++
takes the memory location of destination[0]
(which is not the beginning of the array anymore, since you've changed destination
), looks there, and adds the size of the type of *destination
so that destination[0]
refers to what used to be destination[1]
.
Why should we speculate? We can try it and find out. I compiled the code with gcc -O3 -g
(on x86) and disassembled the result. There were more changes than I expected, so I'll focus in on the bits in the middle where we'd expect the bulk of the differences between the two to be.
The core of the loop in the first case:
0x00000030 <foo+48>: mov %dl,(%edi,%esi,1)
0x00000033 <foo+51>: movzbl 0x1(%ecx),%edx
0x00000037 <foo+55>: inc %eax
0x00000038 <foo+56>: inc %ecx
0x00000039 <foo+57>: mov %eax,%esi
0x0000003b <foo+59>: test %dl,%dl
0x0000003d <foo+61>: jne 0x30 <foo+48>
The core of the loop in the second case:
0x00000080 <foo2+48>: mov %dl,(%eax)
0x00000082 <foo2+50>: movzbl 0x1(%ecx),%edx
0x00000086 <foo2+54>: inc %eax
0x00000087 <foo2+55>: inc %ecx
0x00000088 <foo2+56>: test %dl,%dl
0x0000008a <foo2+58>: jne 0x80 <foo2+48>
On that basis, the second is perhaps a little faster. But really, it won't make much difference in practice. The L1 cache holds both loops just fine and the target memory is uncached so the differences will be moot. Good luck with ever actually measuring a difference between the two.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With