error: cannot convert 'double*' to 'ch

2020-05-01 06:18发布

#include <stdio.h>

void swap( char* pA,  char* pB, unsigned tam) {
    for( unsigned i = 0; i < tam; i++) {
        char tmp = *pA;
        *pA = *pB;
        *pB = tmp;

        pA = pA + 1;
        pB = pB + 1;
    }
}

int main(int argc, char** argv) {
    double a = 1.0;
    double b = 2.0;

    printf("linea: %d - antes a(%f) b(%f)\n", __LINE__, a, b);

    swap(&a, &b, sizeof(double)); //This line gives the error

    printf("linea: %d - despues a(%f) b(%f)\n", __LINE__, a, b);
}

When I call the swap method I get the error message in the title, any idea why? I saw many other posts with solutions but none of them fixed this problem

标签: c
3条回答
霸刀☆藐视天下
2楼-- · 2020-05-01 06:48

Well, your function is expecting a pointer to a character for the first two arguments

void swap( char* pA,  char* pB, unsigned tam) 

but you are passing in pointers to double

double a = 1.0;
double b = 2.0;
swap(&a, &b, sizeof(double)); //This line gives the error

The following would allow you to swap two doubles, unless there is a specific reason you are swapping one byte at a time:

void swap(double *pA, double *pB, unsigned int tam) {
    double tmp = *pA;
    *pA = *pB;
    *pB = tmp;
}
查看更多
【Aperson】
3楼-- · 2020-05-01 06:53

There are a number of ways of writing a generic swap function. If it will be used for only one type (so it doesn't need to be generic), the size argument is not needed and you can pass pointers of the relevant type (double * in the question) and swap using indirection.

extern void double_swap(double *d1, double *d2);

void double_swap(double *d1, double *d2)
{
    double d = *d1;
    *d1 = *d2;
    *d2 = d;
}

There might well be advantages to making that into:

static inline void double_swap(double *d1, double *d2)
{
    double d = *d1;
    *d1 = *d2;
    *d2 = d;
}

This could be placed in a header and used safely.

If it will be used for multiple types, you should use void * in the function arguments (and size_t for the size of the type).

/*
** This declaration belongs in a header if there is more than one
** source file that uses it.  If there is only one file, then it
** should be declared and defined as a static function.  If the
** header doesn't include any other headers that define size_t,
** it should #include <stddef.h> as that's the smallest header
** that does define size_t.  You could make the function static
** inline instead of extern, even if it is in a header.
*/
extern void generic_swap(void *v1, void *v2, size_t size);

/* Implementation 1: Using VLA */
void generic_swap(void *v1, void *v2, size_t size)
{
    char sp[size];
    memmove(sp, v1, size);
    memmove(v1, v2, size);
    memmove(v2, sp, size);
}

You can use memcpy() if you don't mind living dangerously (you should probably add restrict to the v1 and v2 pointer types if you do that). Again, the function could probably be made static inline to good effect — that also applies to the other implementations below.

If you don't like the idea of large objects being allocated on the stack, you can copy the data in chunks, but you have to work quite a bit harder.

enum { CHUNK_SIZE = 64 };

static inline size_t min_size(size_t x, size_t y) { return (x < y) ? x : y; }

/* Implementation 2: Using a fixed size buffer */
void generic_swap(void *v1, void *v2, size_t size)
{
    unsigned char sp[CHUNK_SIZE];
    unsigned char *p1 = v1;
    unsigned char *p2 = v2;
    size_t chunk;
    while ((chunk = min_size(size, CHUNK_SIZE)) != 0)
    {
        memmove(sp, p1, chunk);
        memmove(p1, p2, chunk);
        memmove(p2, sp, chunk);
        p1 += chunk;
        p2 += chunk;
        size -= chunk;
    }
}

Notwithstanding anything that GCC permits, the C standard says you can't increment a void * because there is no known size to increment it by. That's why the pointers are converted to unsigned char *. Clearly, you can tune the chunk size to suit your system. Any power of 2 in the range 16..1024 is probably usable, and other values than a power of 2 can be used if you prefer.

If you don't mind the overhead, you can dynamically allocate a buffer:

/* Implentation 3: Using dynamic memory allocation */
void generic_swap(void *v1, void *v2, size_t size)
{
    char *sp = malloc(size);
    if (sp != 0)
    {
        memmove(sp, v1, size);
        memmove(v1, v2, size);
        memmove(v2, sp, size);
        free(sp);
    }
}

If memory allocation fails, the swap doesn't occur. That's bad, so you might fall back on the 'fixed size buffer and swap in chunks', but that is probably quicker than this anyway.

I would use Implementation 2 in preference to Implementation 3; dynamic memory allocation is expensive. I would probably use Implementation 2 in preference to Implementation 1 as the extra cost of the looping is minimal and using a fixed amount of stack works well. I have not benchmarked any of these to verify my assertions. (If you're swapping megabyte sized lumps of data, you should probably think again — use pointers instead. If you're only swapping smaller chunks, Implementation 1 is simple and safe.)

With any of the generic swap implementations, your main program becomes:

int main(void)
{
    double a = 1.0;
    double b = 2.0;

    printf("linea: %d - antes   a(%f) b(%f)\n", __LINE__, a, b);
    generic_swap(&a, &b, sizeof(double));
    printf("linea: %d - despues a(%f) b(%f)\n", __LINE__, a, b);
    return 0;
}

I'm assuming that at least the declaration of generic_swap() is available before the start of main().

Note that using either double_swap() or generic_swap() means that no casts are necessary in the code. Minimizing casts is A Good Idea™.

See also Universal array element swap in C.

查看更多
做自己的国王
4楼-- · 2020-05-01 06:59

I get the error message in the title ? Because you are passing double variable address and catching with char* so compiler is saying

expected ‘char *’ but argument is of type ‘double *’.

So you have two ways either typecast the address of double variable as char* or catch with double* itself.

Case 1:

void swap( double* pA,  double* pB, unsigned int tam) {
        double tmp = *pA;
        *pA = *pB;
        *pB = tmp;
}

int main(int argc, char** argv) {
        double a = 1.0;
        double b = 2.0;
        printf("linea: %d - antes a(%f) b(%f)\n", __LINE__, a, b);
        swap(&a, &b, sizeof(double)); //This line gives the error
        printf("linea: %d - despues a(%f) b(%f)\n", __LINE__, a, b);
        return 0;
}

Case 2 :- Second way is typecast the address of double variable as char* send it to swap()

void swap( char *pA,  char *pB, unsigned int tam) {
        for( unsigned i = 0; i < tam; i++) {
                char tmp = *pA;
                *pA = *pB;
                *pB = tmp;
                pA = pA + 1;
                pB = pB + 1;
        }
}
int main(int argc, char** argv) {
        double a = 1.0;
        double b = 2.0;
        printf("linea: %d - antes a(%f) b(%f)\n", __LINE__, a, b);
        swap((char*)&a, (char*)&b, sizeof(double)); //typecast &a to (char*)&a
        printf("linea: %d - despues a(%f) b(%f)\n", __LINE__, a, b);
        return 0;
}
查看更多
登录 后发表回答