Pointers Homework

Pages: 1234
I think he wants you to say it can't be done because the function is returning void and takes just one parameter. What he doesn't realise, is this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

void getsize(void* p)
{
    char* s = (char*)p;
    size_t sz = 0;
       
    /* ??? */

    asm("mov    %0,   %%eax\n\t"
        "leave\n\t"
        "ret\n\t"
        ::"m"(sz)
       );
}

int main(void)
{
    char* alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
    size_t sz = 0, end;

    getsize(alphabet);

    asm("mov    %%eax,  %0\n\t"
        :"=m"(sz)
       );

    printf("The length of the alphabet is %ld\n", sz);
    
    return 0;
}


Now, I haven't figured out how to get the size of the array yet, but I'm working on it...
@chrisname
um, I don't know what's this weird assembly stuff you're doing in there but are you sure u're not using the fact that the alphabet is terminated with '\0' ???
because the function is returning void
That was meant as a way to isolate him from all other information. If it can be done inside a function with nothing but a pointer, then it can be done.

are you sure u're not using the fact that the alphabet is terminated with '\0' ???
That depends on how he does it. If he doesn't actually use the zero, then it's alright.
Last edited on
um, I don't know what's this weird assembly stuff you're doing in there but are you sure u're not using the fact that the alphabet is terminated with '\0' ???

That was an example. I don't know how to get the array size without the NULL being there, so I was using that to show it works when I know where to end.

Here's how real programmers do it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

/* return values and parameters are for wimps */
void getsize(void)
{
    char* s = NULL;
    size_t sz = 0;

    /* Get the pointer to alphabet */
    asm("pop    %0\n\t"
        :"=m"(s)
       );
       
    /* ??? */

    /* Put sz in eax as the return value */
    asm("mov    %0,   %%eax\n\t"
        "leave\n\t"
        "ret\n\t"
        ::"m"(sz)
       );
}

int main(void)
{
    char* alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
    size_t sz = 0, end;

    /* Put a pointer to alphabet on the stack and call getsize */
    asm("push   %0\n\t"
        "call   getsize\n\t"
        ::"m"(alphabet)
       );

    /* Get the return value of getsize and store it in sz */
    asm("mov    %%eax,  %0\n\t"
        :"=m"(sz)
       );

    /* Now sz contains the length of the array */
    printf("The length of the alphabet is %ld\n", sz);
    
    return 0;
}


That depends on how he does it. If he doesn't actually use the zero, then it's alright.

Huh? I thought the excercise was to see if it was possible to get the byte-size of a pointer without knowing where it ended..?
Last edited on
@chrisname
ok, I think I got what you're doing there, you re using directly the program stack to pass the parameters in your function instead of having your c++ compiler do it for you, right?? but then, that's the only thing you do... you don't suggest any solution to the problem :/
I give a workaround for the limitations helios gives you, though :)
hahahahahaha, yes, that's true
Mainly, I did that just to annoy him. Didn't seem to work, though.

Also, looking at page 1, you guys need my help on the C string library:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include <lib/string.h>

/**
 * itoa: convert the integer i into a string, buf, in the base base.
 * @i: the integer
 * @buf: the string to store the result in
 * @base: the numeric base to store it in
 */
void itoa(int i, char* buf, int base)
{
    char* p = buf,
        * p1 = NULL,
        * p2 = NULL;
    unsigned long ui = i;
    
    if (base == 10 && i < 0) {
        *p++ = '-';
        buf++;
        ui = -i;
    }
    
    /* Create a null-terminated string buf and store the string form of i in it */
    do {
        int tmp = ui % base;
        *p++ = (tmp < 10) ? tmp + '0' : tmp + 'a' - 10;
    } while (ui /= base);
    
    *p = 0;
    
    /* Reverse buf */
    p1 = buf;
    p2 = p - 1;
    
    while (p1 < p2) {
        char tmp = *p1;

        *p1 = *p2;
        *p2 = tmp;
        
        p1++;
        p2--;
    }
}

void* memset(void* ptr, int value, size_t n)
{
    char* p = (char*)ptr;

    while (n--)
        *p++ = value;
    
    return p;
}

void* memcpy(void* dest, const void* src, size_t n)
{
    while (n--)
        *(char*)dest++ = *(char*)src++;
    
    return dest;
}

size_t strlen(const char* str)
{
    size_t len;
    
    for (len = 0; *str; str++, len++);
    
    return len;
}

int strncmp(const char* s1, const char* s2, size_t n)
{
    while (*s1 && *s2 && n--) {
        if (*s1 != *s2)
            return *s1 - *s2;

        s1++;
        s2++;
    }
    
    return 0;
}

int strcmp(const char* s1, const char* s2)
{
    while (*s1 && *s2) {
        if (*s1 != *s2)
            return *s1 - *s2;

        s1++;
        s2++;
    }
    
    return 0;
}

int memcmp(const void* p1, const void* p2, size_t n)
{
    while (n--) {
        if (*(char*)p1 != *(char*)p2)
            return *(char*)p1 - *(char*)p2;
        p1++;
        p2++;
    }

    return 0;
}


char* strchr(const char* s, char c)
{
    while (*s) {
        if (*s == c)
            return (char*)s;
        s++;
    }
    
    return NULL;
}

char* strncpy(char* dest, const char* src, size_t n)
{
    while (*src && n--)
        *dest++ = *src++;
        
    return dest;
}

char* strncat(char* dest, const char* src, size_t n)
{
    dest += (strlen(dest) - 1);
    
    while (*src && n--)
        *dest++ = *src++;
    
    return dest;
}


char* strcpy(char* dest, const char* src)
{
    while (*src)
        *dest++ = *src++;
        
    return dest;
}

char* strcat(char* dest, const char* src)
{
    dest += (strlen(dest) - 1);
    
    while (*src)
        *dest++ = *src++;
    
    return dest;
}


I haven't finished yet; I don't know what a few functions (like strxspn) are meant to do, but the ones I've written there (in like five minutes) all work. I haven't done some of them yet (like strstr) because I can't remember how to (I did it before, but I forget how :( ).

Edit: I may have gotten the return value for some of them wrong (i.e. they return char* or void* when they should just return void); as I say, I wrote them because I was bored in like five minutes (I stopped 'cause I got bored :l).

Here's a challenge for you guys: write an implementation of memmove(). Not memcpy, 'cause that's easy, but memmove().
Last edited on
Your shenanigans don't affect me.
"Make your code last a thousand years." That's the wisdom passed down by our grand masters in their testament. Reject it at your own peril.
Last edited on
`(^o^)'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <cstdlib>
using namespace std;

void * my_memcpy ( void * dest, const void * src, size_t num );
void * my_memmove ( void * dest, const void * src, size_t num );

int main()
{
    
    char str1[] = "memmove can be very useful......";
    char str2[] = "memmove can be very useful......";
    
    
    cout << "initial string: \t" << str1 << endl;
    
    my_memcpy(str1+20,str1+15,11);
    my_memmove(str2+20,str2+15,11);
        
    cout << "(using my_memcpy): \t" << str1 << endl;
    cout << "(using my_memmove): \t" << str2 << endl;
    
    system("pause");
    return 0;
}

void * my_memcpy ( void * dest, const void * src, size_t num )
{
     for (int i=0; i<num; i++)
     {
         *((char*)(dest)+i)=*((char*)(src)+i);
     }
}

void * my_memmove ( void * dest, const void * src, size_t num )
{
     void * buffer=malloc(num);
     my_memcpy(buffer,src,num);
     my_memcpy(dest,buffer,num);
     free(buffer);     
}
Your shenanigans don't affect me.

Hehehe...

@m4ster r0shi
Ok. Now do it without an itermediary buffer. Also, don't use system(); it's avoidable in literally every situation.
@helios
ok, it's not exactly the answer to your question but it's really cool! :D don't you think?? (it IS so... plz acknowledge it... ;) )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <cstdlib>
#include <iostream>

using namespace std;

template<class T>
class SmartArray
{
      private:
      T * first; //pointer to the first element
      int sz; //size of the array
      
      public:
      SmartArray(int n):sz(n) {first=new T[n];}
      ~SmartArray() {delete[] first;}
      inline int size() const {return sz;}       
      T& operator[](int i) {return *(first+i);}           
      const T& operator[](int i) const {return *(first+i);}
      
      friend ostream & operator<<(ostream & os, const SmartArray & smarr)
      {
        int i;
        os << '{';
        for (i=0; i<smarr.size(); i++)
        {
            os << smarr[i] << ',';
        }
        os << '\b';
        os << '}' << flush;
        return os;
      }
};

template<class T>
void getsize(void*p);
/*
since you want getsize to return void and only take a pointer
as a param, I'm gonna have to do something tricky here...
*/

template <class T>
struct GetsizeParam
{
       //getsize actual argument
       SmartArray<T> * psmarr;
       
       //getsize return value
       int ret_val;
};

int main()
{ 
    SmartArray<int> arr(10);
    
    int i;
    for (i=0; i<arr.size(); i++)
    {
        arr[i]=i+1;
    }
    
    cout << "your smart array: ";
    cout << arr << endl;
    
    //geting the size from the actual array
    cout << "\n(using size function of the array)" << endl;
    cout << "your smart array's size is: " << arr.size() << endl;
    
    //geting the size from a pointer to the array
    GetsizeParam<int> gspar;
    SmartArray<int> * parr;
    parr=&arr;
    gspar.psmarr=parr;
    cout << "\n(calling getsize with a pointer to the array)" << endl;
    getsize<int>(&gspar);
    cout << "your smart array's size is: " << gspar.ret_val << endl;
    
    system("pause");
    return 0;
}

template<class T>
void getsize(void*p)
{
     GetsizeParam<T> * param=(GetsizeParam<T>*)p;
     param->ret_val=param->psmarr->size();
     return;     
}


@chrisname
I'm currently working on a non-buffer version for memmove... I guess I'll be posting it soon...
Last edited on
4. What's the difference between char string[]="Hello, World!\n"; and char *string="Hello, World!\n";?

i guess the first one is null terminated and the other is not..
try

1
2
char * str="asdf";
cout << str << endl;


it will print "asdf". now, if it wasn't null terminated, how would you suggest it would know when to stop printing???
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;

int main() {
    char string1[]="Hello, World!\n";
    char *string2="Hello, World!\n";
    //works!
    string1[14] = 'x';
    cout << string1[14] << endl;

    //dont work! :(
    string2[14] = 'x';
    cout << string2[14] << endl;
    return 0;
}


edit: dont know though if that proves anything.. LOL
Last edited on
m4ster r0shi: That code is bad and you should feel bad about it.
ok here one more answer from me, if it's not the null terminated issue.. maybe the difference is that the first one copies the value of the of the string literal which is a constant.. and the other just points to where the string literal is found.. so modifying the value of that pointer causes the program to crash..

hmm... that's what i think..
Last edited on
@helios
LOL xD what's bad about it???
@blackcoder41
check this out:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
using namespace std;

int getlen(const char * str);

int main() {
    char string1[]="Hello, World!\n";
    char *string2="Hello, World!\n";
    
    cout << "string1 length: ";
    cout << getlen(string1) << endl;
    
    cout << "string2 length: ";
    cout << getlen(string2) << endl;
    
    system("pause");
    return 0;
}

int getlen(const char * str)
{
    int len=0;
    while (*str++) len++;
    return len;
}


getlen stops the first time it finds a zero. both calls return 14 as the length, so both strings end with a zero :)
Last edited on
maybe you're right

but on my system this still give both zero

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
using namespace std;

int main() {
    char string1[]="Hello, World!\n";
    char *string2="Hello, World!\n";

    cout << string1[15]-0 << endl;
    cout << string2[15]-0 << endl;
    return 0;
}



which exceed the the valid indices, maybe it's just a coincidence.. though still not sure.. maybe helios should say the answer now..
Pages: 1234