C newbie question

Business_Woman

Active Member

Reaction score: 6
Messages: 152

Hai,

Trying to write a function to calculate string length.

PHP:
int strnlen(char *str){
         
     while(*str != '\0'){
                 str++;
     }
     return (int)str;
     }
But that won't work, why?
 

avilla@

Well-Known Member
Developer

Reaction score: 59
Messages: 258

is that returning big, big numbers? if str is the pointer to the char[], it won't start at 0... better do that with a counter...

PHP:
for (i = 0; str[i] != '\0'; ++i)
        ;
return i;
...or, if you want to keep it that way, record the value of str at the beginning and subtract it from str when returning...

PHP:
for (str_init = str; *str != '\0'; ++str)
        ;
return (int)(str - str_init);
it *should* work, but it doesn't make sense)
 

avilla@

Well-Known Member
Developer

Reaction score: 59
Messages: 258

ephemera said:
Code:
return strchr(str,0)-str;
if you're going to include <string.h>, then you have strlen() too... :p
 
OP
OP
Business_Woman

Business_Woman

Active Member

Reaction score: 6
Messages: 152

I found a way that works

PHP:
int strlen(char *str){
    
    char *p = str;
    while(*p != '\0'){
             p++;
    }        
             return p-str;
             }
But what is the value of str?
 

avilla@

Well-Known Member
Developer

Reaction score: 59
Messages: 258

Business_Woman said:
I found a way that works

PHP:
int strlen(char *str){
    
    char *p = str;
    while(*p != '\0'){
             p++;
    }        
             return p-str;
             }
which is exactly the second example i made, with a while in place of the for (not elegant, and longer) :)
anyway i suggest using my first example

But what is the value of str?
str is the pointer to the array of characters (the string), and it contains the address of memory to which it refers (which is the initial address of the array of characters). *str is, as you seem to know, the value stored in that memory cell
 

SirDice

Administrator
Staff member
Administrator
Moderator

Reaction score: 7,685
Messages: 30,622

Ok.. First off, pointer arithmetic is a bad, bad idea. Sooner or later you will shoot yourself in the foot with it.

Now, lets explain
Code:
int strlen(char *str){
    
    char *p = str;
    while(*p != '\0'){
             p++;
    }        
    return p-str;
}
Str will be a pointer to a memory address where your string starts. P is also a pointer and you've assigned it the value of str. Now both p and str point at the same memory location.

By incrementing p until the end of the string it will point to the last address. Subtracting the last address from the first (where str is still pointing to) you get the number of bytes. Ergo, the string length.
 

ephemera

Member

Reaction score: 2
Messages: 33

Memory is made up of bytes and is numbered from 0 to whatever amount you have available on your m/c.

strlen() is called with str pointing to the string (say) "hello" already stored in memory starting at address (say) 756, like shown below:

Code:
---------------------------
... |h |e |l |l |o |\0| ...
---------------------------
     ^
     str(756)
     ^
     p(756)
After char *p = str; both str and p contain the address (or point to mem. location) 756.

If you dereference a pointer you get whats stored in its mem. location. For example *str will give the ASCII char. 'h'.

After the while loop exits you have:

Code:
---------------------------
... |h |e |l |l |o |\0| ...
---------------------------
     ^              ^
     str(756)       p(761)
Subtracting the pointers str and p gives p-str = 761-756 = 5
 

SirDice

Administrator
Staff member
Administrator
Moderator

Reaction score: 7,685
Messages: 30,622

ephemera said:
Memory is made up of bytes and is numbered from 0 to whatever amount you have available on your m/c.
Technically, every process gets it's own 4GB address space regardless of the amount of physical memory you have ;)
 

ephemera

Member

Reaction score: 2
Messages: 33

SirDice said:
Technically, every process gets it's own 4GB address space regardless of the amount of physical memory you have ;)
Sure, but we don't want to overwhelm a newbie who is struggling to understand pointers. :)
 

vivek

Aspiring Daemon

Reaction score: 194
Messages: 805

Why reinvent wheel (learning may be objective here, in that case open headers and related files) ? Just use provided functions.
 

SirDice

Administrator
Staff member
Administrator
Moderator

Reaction score: 7,685
Messages: 30,622

vivek said:
Why reinvent wheel (learning may be objective here, in that case open headers and related files) ? Just use provided functions.
IMO making your own functions even if the same standard function already exist will increase your knowledge. So I think it's good to do stuff like this, learn how it works and then use the already provided functions :e
 

papanyanz

New Member


Messages: 19

Your own fnction will work 10000 times slower than one provided by c library. Try to compare them - run in the loop for an 1000000 times and use timers to get intervals...

Library functions recently use hardware capabilities to speed up execution ...
try to write your own "bitblt"-like - you'll see how each pixel was drawn :)
 
OP
OP
Business_Woman

Business_Woman

Active Member

Reaction score: 6
Messages: 152

Hi, i have just one last question ;)

After the sucess with the strlen function i tried to write my own version of strcpy, but something must be wrong because my program segfaults when trying to use it.

I want the function to return a pointer to the copied string

PHP:
char *strcopy(const char *src, char *dest){

while(*dest++ = *src++);

return dest;
}
Also what is the difference between
char *p;

*p = 'p'
*p = "p"
Do i still have to point p somewhere?, and where would that be?

//thanks
 

mickey

Well-Known Member

Reaction score: 85
Messages: 427

Business_Woman said:
I want the function to return a pointer to the copied string

PHP:
char *strcopy(const char *src, char *dest){

while(*dest++ = *src++);

return dest;
}
Because you are incrementing your dest pointer, while copying the string, in the end it will point to the memory location right after the end of the destination string. Using that
pointer surely gives a segfault. You would need to save a copy
of the original dest pointer and return that instead.

Also what is the difference between
char *p;

*p = 'p'
This assigns the ASCII code of the letter 'p' to the memory location p points to.

This assigns a pointer to the memory location of the NUL
terminated string "p" to the memory location, where p points to.
As p is a "char *", this does not make much sense anyways. It
could make sense if p was of type "char **".

Do i still have to point p somewhere?, and where would that be?
p must point to a memory location, owned by and writable by the process. Otherwise a segfault is for sure. This could for example be the memory of an automatic variable, as in
Code:
char str[256];
char *p = &str;
or a memory block, allocated by means of malloc(), calloc(), etc.
 

Alt

Aspiring Daemon

Reaction score: 82
Messages: 726

Business_Woman said:
Also what is the difference between
char *p;

*p = 'p'
*p = "p"
Do i still have to point p somewhere?, and where would that be?
You will got segfault this way, cus char* is only pointer, he not own any memory. When you assign this way will write to random memory location what leads to segfault
 

Eponasoft

Active Member

Reaction score: 11
Messages: 217

papanyanz said:
Your own fnction will work 10000 times slower than one provided by c library. Try to compare them - run in the loop for an 1000000 times and use timers to get intervals...

Library functions recently use hardware capabilities to speed up execution ...
try to write your own "bitblt"-like - you'll see how each pixel was drawn :)
I think you're missing the point...
 

ephemera

Member

Reaction score: 2
Messages: 33

papanyanz said:
Your own fnction will work 10000 times slower than one provided by c library. Try to compare them - run in the loop for an 1000000 times and use timers to get intervals...
Here's an i386 optimised version of strlen() from Solaris:
http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/i386/gen/strlen.s

Haven't benchmarked it but looking at the code it's obvious that it won't give anything like the 10000x speed improvement you mentioned - more likely a single digit factor of increase in speed. :)

There is a reduction in memory access (~4x) but since both the programs are cache friendly (picture perfect spacial locality of reference) I think the main speed improvement is coming from the ~4x reduction in number of branches (working with a word at time instead of byte).
 

Alt

Aspiring Daemon

Reaction score: 82
Messages: 726

She just doing exercises - why you boring about it :/
 

papanyanz

New Member


Messages: 19

Alt said:
She just doing exercises - why you boring about it :/
That's good - maybe this is the best way to learn pointers and string manipulations.What i wanted to say - that in real applications use ONLY library ones...

Here's an i386 optimised version of strlen() from Solaris:
http://src.opensolaris.org/source/xr...6/gen/strlen.s

Haven't benchmarked it but looking at the code it's obvious that it won't give anything like the 10000x speed improvement you mentioned - more likely a single digit factor of increase in speed.
Well - how about memcpy please? Just now i've no time to check code - if it uses much advanced techniques...
Anyway - there was a time when i was wondering,why
PHP:
for (int i=0;i<=1000000;i++) a[i]=b[i];
is working twice slower compared to ;)
PHP:
for (int i=0;i<=500000;i++) {
a[i]=b[i];
a[i+500000]=b[i+500000];
}
 

Eponasoft

Active Member

Reaction score: 11
Messages: 217

That's because of the overhead of the 'for' loop in PHP. Assignments, even of arrays, are much faster than a loop pass. So being able to do two assignments per pass at different offsets is going to be faster than one assignment per pass. It's probably the same in normal C code, though I imagine that the difference isn't going to be so huge.
 
Top