我正在通过尝试实现一个能够交换字符串和数组的通用交换函数来学习 C。我认为这是可能的,因为字符串和数组本质上是内存中的数组,并且我不交换实际字节,而只交换指针。这是我的实现:
#include "stdio.h"
void swap(void **a, void **b) {
void *tmp;
tmp = *b;
*b = *a;
*a = tmp;
}
void print_array(char *c, int size) {
for (int i = 0; i < size; ++i) {
printf("%c ", c[i]);
}
printf("\n");
}
int main() {
char *h = "hell";
char *w = "world";
printf("%s %s\n", h, w);
swap((void **)&h, (void **)&w);
printf("%s %s\n", h, w);
char c[5] = { 'a', 'e', 'i', 'o', 'u' };
char d[3] = { '1', '2', '3' };
print_array(c, 5);
print_array(d, 3);
swap((void **)&c, (void **)&d);
return 0;
}
结果是:
hell world
world hell
a e i o u
1 2 3
*** stack smashing detected ***: terminated
Aborted (core dumped)
如您所见,这个通用交换函数可以交换两个字符串,但当输入是数组时,它会触发核心转储。我不明白我对指针和数组的理解哪部分是错误的。
不能使用相同的函数来交换指针和交换数组。
例如要交换两个数组,您需要交换它们的元素。
至于错误,例如表达式
&c
的值是数组c
的第一个元素的地址值。
函数内地址解引用操作
swap
*b = *a;
读取数组所占用的内存,即其元素
{'a', 'e', 'i', 'o', 'u'};
作为导致未定义行为的地址值。
您可以设计一个通用交换函数来交换任何类型的对象,但要使交换成为可能,对象必须具有相同的大小。这里的字符串指针确实具有相同的大小,
sizeof(char *)
,在大多数平台上与sizeof(void *)
相同,因此您的代码应该按预期工作,尽管它违反了严格的别名规则。相反,sizeof(c) != sizeof(d)
所以交换这些数组是不可能的。