#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);
}
当我调用swap方法时,我在标题中收到错误消息,任何想法为什么?我看到很多其他帖子都有解决方案,但没有一个解决了这个问题
答案 0 :(得分:2)
编写通用交换功能有很多种方法。如果它只用于一种类型(因此它不需要是通用的),则不需要size参数,你可以传递相关类型的指针(问题中为double *
)并交换使用间接。
extern void double_swap(double *d1, double *d2);
void double_swap(double *d1, double *d2)
{
double d = *d1;
*d1 = *d2;
*d2 = d;
}
将其变为:
可能会有好处static inline void double_swap(double *d1, double *d2)
{
double d = *d1;
*d1 = *d2;
*d2 = d;
}
这可以放在标题中并安全使用。
如果它将用于多种类型,则应在函数参数中使用void *
(对于类型的大小,应使用size_t
。)
/*
** 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);
}
如果您不介意生活危险,可以使用memcpy()
(如果您这样做,可以将restrict
添加到v1
和v2
指针类型)。同样,函数可能会static inline
达到良好效果 - 这也适用于下面的其他实现。
如果您不喜欢在堆栈上分配大对象的想法,您可以以块的形式复制数据,但是您必须更加努力地工作。
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;
}
}
尽管GCC允许,C标准表示你不能增加void *
,因为没有已知大小可以增加它。这就是指针转换为unsigned char *
的原因。显然,您可以调整块大小以适合您的系统。 16..1024范围内的任何2的幂都可以使用,如果您愿意,可以使用除2的幂之外的其他值。
如果您不介意开销,可以动态分配缓冲区:
/* 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);
}
}
如果内存分配失败,则交换不会发生。这很糟糕,所以你可能会回到固定大小的缓冲区并交换块,但这可能比这更快。
我会使用Implementation 2而不是Implementation 3;动态内存分配很昂贵。我可能会使用实现2而不是实现1,因为循环的额外成本很小,并且使用固定数量的堆栈效果很好。我没有基准测试任何 这些来验证我的断言。 (如果您正在交换兆字节大小的数据块,您应该再考虑一下 - 使用指针代替。如果您只是交换较小的块,则实现1非常简单且安全。)
使用任何通用交换实现,您的主程序将变为:
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;
}
我假设至少generic_swap()
的声明在main()
开始之前可用。
请注意,使用double_swap()
或generic_swap()
表示代码中不需要强制转换。最小化演员阵容是一个好主意。
答案 1 :(得分:1)
好吧,你的函数期望指向前两个参数的字符
void swap( char* pA, char* pB, unsigned tam)
但你传递的指针是双重
double a = 1.0;
double b = 2.0;
swap(&a, &b, sizeof(double)); //This line gives the error
以下内容允许您交换两个双打,除非您有特定原因要一次交换一个字节:
void swap(double *pA, double *pB, unsigned int tam) {
double tmp = *pA;
*pA = *pB;
*pB = tmp;
}
答案 2 :(得分:0)
我在标题中收到错误消息?因为您传递的是双变量地址并且正在使用ftp_append(
resource $ftp,
string $remote_file,
string $local_file
[, int $mode = FTP_IMAGE ]
)
,所以编译器会说
期望'char *'但参数的类型为'double *'。
因此,您有两种方式char*
双变量的地址<{1}}或typecast
本身。
案例1:
char*
案例2: -
第二种方法是将double*
的双变量地址强制转换为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;
}
char*