我正在通过try 实现一个能够交换字符串和数组的通用交换函数来学习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)

正如您所看到的,这个通用的交换函数可以交换两个字符串,但当输入是数组时,它会触发核心转储.我不明白我对指针和数组的理解哪一部分是错误的.

推荐答案

char c[5] = { 'a', 'e', 'i', 'o', 'u' };

数组不是指针.&c不是char **.

是的,您可以对数组执行*c*(c + 2)以及其他类似指针的操作,这自然会让您认为它是指针,但事实并非如此.

这只是因为在许多情况下,数组对于指针(指向其第一个元素)是implicitly converted("衰变"),包括那些情况.结果指针是一个临时指针(右值),它在需要时动态计算,否则不会存储在内存中.存储在数组中的唯一东西是它的元素.

数组不会衰减为指针的情况之一是&c.这不会返回char **(指向char的指针),这是不可能的,因为衰变产生的指针是计算出来的,而不是持久存储在内存中的.

取而代之的是一个类型为char (*)[5]的指针(指向由5char组成的数组的指针),它的值与&c[0]相同,但类型不同(&c[0]char *).

因为没有指向掉期的底层指针,所以您想要的东西是不可能的.

您可以做的最接近的事情是遍历每个数组元素并交换它.这要求数组具有相同的长度.大概是这样的:

#include <stddef.h>
#include <stdio.h>

void swap_memory(void *a, void *b, size_t n)
{
    char *ca = a;
    char *cb = b;
    char *end_ca = ca + n;
    while (ca != end_ca)
    {
        char tmp = *ca;
        *ca = *cb;
        *cb = tmp;
        ca++;
        cb++;
    }
}

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_memory(&h, &w, sizeof(char *));
    printf("%s %s\n", h, w);

    char c[5] = { 'a', 'e', 'i', 'o', 'u' };
    char d[5] = { '1', '2', '3' };
    swap_memory(c, d, 5); // or `(&c, &d, 5)`, doesn't matter
    print_array(c, 3);
    print_array(d, 5);

    return 0;
}

C++相关问答推荐

函数指针始终为零,但在解除引用和调用时有效

创建一个fork导致fget无限地重新读取文件

为什么C语言允许你使用var =(struct NAME){

为什么内核使用扩展到前后相同的宏定义?

C由四个8位整数组成无符号32位整数

自定义变参数函数的C预处置宏和警告 suppress ?

在C++中使用函数指针的正确语法

为什么该函数不将参数值保存到数据 struct 中?

如何使用C for Linux和Windows的标准输入与gdb/mi进行通信?

如何识别Linux中USB集线器(根)和连接到集线器(根设备)的设备(子设备)?

使用sscanf获取零个或多个长度的字符串

链接到底是如何工作的,我在这里到底做错了什么

错误...的多个定义(&Q)首先在这里定义&

理解bzip2的BZ2_解压缩函数中的状态重新分配

CS50判断灯泡运动的问题,判断时多出一个灯泡,但不在终端上

如何在c中使用具有不同变量类型的内存分配?

从Raku nativecall调用时精度不同

C 语言中 CORDIC 对数的问题

创建 makefile 来编译位于不同目录中的多个源文件

返回指向函数内声明的复合文字的指针是否安全,还是应该使用 malloc?