2

I'm making a function which receives array of any datatype and reverse it elements.

void f(void *p, int size)
{
  for(int i=0; i<=size/2; i++)
  {
    swap(p+i, p+size-i-1);
  }
}

but problem is how can i implement swap function which swap their content without dereferencing void pointers?

iammilind
  • 68,093
  • 33
  • 169
  • 336
Furqan
  • 268
  • 1
  • 13

6 Answers6

6

Or you could use the std::reverse function

int main()
{
    int  data[] = { 1, 2, 3, 4, 5, 6, 7};
    std::reverse(data, data + sizeof(data)/sizeof(data[0]));

}
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • +1 vote for the brief answer in C++. (I don't know why there's a -1 vote... it's surely a good solution). – Stan Jul 23 '11 at 08:15
3

Since you tagged as C++, I'm assuming that you can use template. One possible solution:

template<typename T>
void f(T *p, int size) {
    for(int i=0;i<=size/2;i++) {
        swap(p[i], p[size-i-1]);
    }
}
fbafelipe
  • 4,862
  • 2
  • 25
  • 40
  • 1
    You could use swap(). That way if the type has its own effecient version of swap() this will be used. ie if T == std::vector you get a much more effecient swap than using a temporary (as you are copying the vector multiple times). – Martin York Jul 23 '11 at 07:52
  • 1
    Also the identifier _T is reserved in most situations so best to avoid it. – Martin York Jul 23 '11 at 07:52
  • i think we cannot use '[]' with void pointers.Correct me if I'm wrong? – Furqan Jul 23 '11 at 13:24
  • 1
    @furqan: In the same way you can't do pointer arithmatic on void*. That is why the function is templated so that it gets the real type information and not void* – Martin York Jul 23 '11 at 15:57
  • @furqan After reading Martin's comments I googled it and findout that some libraries define a macro named _T, not a reserved keyword but still good to avoid. – fbafelipe Jul 23 '11 at 17:03
  • @fbafelipe: The compiler and libraries that go with the compiler are allowed to use _T as an identifier. `You` as a developer are **NOT**. see: http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier/228797#228797 – Martin York Jul 23 '11 at 17:25
  • @furqan: If you think it allows it then you are doing something else (not what I think you are doing). Pointer asthmatic on a void pointer is meaningless and thus you get a compile time error: `pointer of type ‘void *’ used in arithmetic` – Martin York Jul 23 '11 at 17:29
2

An ugly C example, enjoy it:

#include <stdio.h>

void* f(void * p, size_t blockSize, size_t wholeSize){
    int i;
    unsigned char *begin, *end, temp;

    begin = (unsigned char*) p;
    end = (unsigned char*) p + wholeSize - blockSize;

    while(end>begin){
        for(i=0; i<blockSize; i++){
            temp = begin[i];
            begin[i] = end[i];
            end[i] = temp;
        }
        begin += blockSize;
        end -= blockSize;
    }

    return p;
}

int main()
{
    int i;

    double da[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int ia[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    char ca[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    f(da, sizeof(da[0]), sizeof(da));
    f(ia, sizeof(ia[0]), sizeof(ia));
    f(ca, sizeof(ca[0]), sizeof(ca));

    for(i=0; i<10; i++){
        printf("da[%d]=%lf ia[%d]=%d ca[%d]=%d\n", i, da[i], i, ia[i], i, (int)ca[i]);
    }

    return 0;
}
Stan
  • 787
  • 5
  • 16
  • @furqan: I'd like to comment the efficiency of the function may be low, because of the one-byte operation... however, maybe it's fit for you. – Stan Jul 23 '11 at 08:20
1

If you use C++ then why not to use templates:

template<typename T>
void f(T* const p,int size)  // return changed to `void`
{
  // same logic
}

This will create a copy of this function f for any type you pass (e.g. int[], char[], A[]). Above function can still be improved if you want:

template<typename T, int size>
void f(T (&p)[size])  // don't have to pass sizeof array explicitly
{
  // same logic
}

usage:

int a[] = { ... };
f(a);
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • Actually I'm first year student, Didn't know about templates and memcpy and size_t.I'm doing my hobby project for self learning which i dont know how it is tagged homework.Is there any other way? – Furqan Jul 23 '11 at 07:47
  • @furqan, other ways are there but not cleaner. Also, I am not using `size_t` or `memcpy` here; just your same logic with `template`s – iammilind Jul 23 '11 at 07:49
  • Note: `p+size-i` should be `p+size-i-1`. You have an off by one error. – Martin York Jul 23 '11 at 07:50
  • Note that you want to swap p[i] with p[size-i-1], not p[size-i]. That would cause a buffer overflow. – fbafelipe Jul 23 '11 at 07:52
0

You can't do it. You need at least the size of one element of the array.

Or if it's not C but C++ you can make the function a template.

BenjaminB
  • 1,809
  • 3
  • 18
  • 32
-1
void swap(void *a, void *b, size_t size) {
  char buf[size]; //can be malloc if size to too big

  memcpy(temp, b,    size);
  memcpy(b,    a,    size);
  memcpy(a,    temp, size);
}
Viren
  • 2,161
  • 22
  • 27
  • You missunderstood what he wants. He wants to swap the content of one array (reverse it), not exchange two array. – BenjaminB Jul 23 '11 at 07:43
  • Using memcpy is a bad idea in C++ and nearly always wrong. This is because most types have copy/move constructors that have side effects. – Martin York Jul 23 '11 at 07:54