如何在没有malloc的情况下使用交换功能?

如何在没有malloc的情况下使用交换功能?,c,pointers,malloc,swap,C,Pointers,Malloc,Swap,我想创建没有malloc的void指针。但是通过交换值和使用void指针,我看不到不使用malloc的解决方案 有没有一种方法可以不使用malloc进行这种操作。我在考虑双指针,但这也不是解决方案 徖 #include <stdio.h> // Standard library functions for file input and output #include <stdlib.h> // Standard library used for memory alloca

我想创建没有malloc的void指针。但是通过交换值和使用void指针,我看不到不使用malloc的解决方案

有没有一种方法可以不使用malloc进行这种操作。我在考虑双指针,但这也不是解决方案

#include <stdio.h> // Standard library functions for file input and output
#include <stdlib.h> // Standard library used for memory allocation, process control, and conversions

typedef unsigned char byte_t;

// Declaration of the function
void genericSwap(void *pdata1, void *pdata2, byte_t nBytes);

// Global variable
unsigned int dataFloat = 0; // this will help us as a flag to differentiate
                            // between a float or integer

int main() // main program
{
  int sw;             // integer value for switch
  int a = 0, b = 0;   // declaring integer a and b
  char x = 0, y = 0;  // declaring character x and y
  float c = 0, d = 0; // declaring float c and d
  for (;;)            //  infinite loop
  {
    printf("\nPlease enter your choice:\n'1' for integer value.\n'2' for "
           "character value.\n'3' for float value.\n'0' for exit. \n : ");

    scanf_s("%d", &sw); // choose the input for the switch function

    switch (sw) // switch function
    {
    case 1: // case 1 for selecting integer operations
      printf("\nPlease enter the values for a and b \n : ");
      scanf_s("%d%d", &a, &b); // choose the input for the integer operation
      printf("\nValues before swap\na=%d\tb=%d", a, b);

      genericSwap(
          &a, &b,
          sizeof(int)); // calling the swap function with address of a and b

      printf("\nValues after swap\na=%d\tb=%d", a,
             b); // printing the swap values
      break;

    case 2: // case 2 for selecting character operations
      printf("\nPlease enter the values for a and b \n : ");
      scanf_s(" %c", &x);
      scanf_s(" %c", &y);

      printf("\nValues before swap\na= %c\tb= %c", x, y);

      genericSwap(
          &x, &y,
          sizeof(char)); // calling the swap function with address of x and y

      printf("\nValues after swap\na= %c\tb= %c", x, y);
      break;
    case 3:          // case 3 for selecting float operations
      dataFloat = 1; // indicate that the float operation has been selected
      printf("\nPlease enter the values for a and b \n : ");
      scanf_s("%f%f", &c, &d);

      printf("\nValues before swap\na= %.2f\tb= %.2f", c, d);

      genericSwap(
          &c, &d,
          sizeof(float)); // calling the swap function with address of c and d

      printf("\nValues after swap\na= %.2f\tb= %.2f", c, d);
      break;

    case 0: // terminate the application
      exit(1);
      break;

    default: // when no appropriate selection has been made
      printf("\nYou have entered the wrong choice");
      break;
    }
  }
}

// define function
void genericSwap(void *pdata1, void *pdata2, byte_t nBytes) {
  void *temp = NULL; // setting void pointer temp to NULL

  temp = malloc(nBytes); // allocating memory to void pointer
  if (nBytes > 1) // if the size is more then 1 byte this means it is another
                  // value then a character
  {
    if (dataFloat == 1) // if dataFloat is equal to 1 then it is a float type
    {
      dataFloat = 0;                         // resetting dataFloat to 0
      *((float *)temp) = *((float *)pdata1); // typecasting the pointer to float
      *((float *)pdata1) = *((float *)pdata2);
      *((float *)pdata2) = *((float *)temp);

    } else {
      *((int *)temp) = *((int *)pdata1); // typecasting the pointer to integer
      *((int *)pdata1) = *((int *)pdata2);
      *((int *)pdata2) = *((int *)temp);
    }
  } else {
    *((char *)temp) = *((char *)pdata1); // typecasting the pointer to character
    *((char *)pdata1) = *((char *)pdata2);
    *((char *)pdata2) = *((char *)temp);
  }

  free(temp); // de-allocating memory

  temp = NULL; // making the pointer temp to NULL
}
#包括//用于文件输入和输出的标准库函数
#包括//用于内存分配、进程控制和转换的标准库
typedef无符号字符字节;
//职能声明
void genericSwap(void*pdata1,void*pdata2,字节);
//全局变量
无符号int-dataFloat=0;//这将有助于我们作为一个标志来区分
//介于浮点或整数之间
int main()//主程序
{
int sw;//开关的整数值
int a=0,b=0;//声明整数a和b
字符x=0,y=0;//声明字符x和y
浮点c=0,d=0;//声明浮点c和d
for(;;)//无限循环
{
printf(“\n请输入您的选项:\n'1'表示整数值。\n'2'表示”
“字符值。\n'3'表示浮点值。\n'0'表示退出。\n:”;
scanf_s(“%d”,&sw);//选择开关功能的输入
开关(sw)//开关功能
{
案例1://选择整数运算的案例1
printf(“\n请输入a和b的值:”);
scanf_s(“%d%d”,&a和&b);//选择整数运算的输入
printf(“\n交换前的值\na=%d\tb=%d”,a,b);
通用软件(
&a、 &b,
sizeof(int));//调用地址为a和b的交换函数
printf(“\n交换后的值\na=%d\tb=%d”,a,
b) ;//打印交换值
打破
案例2://选择字符操作的案例2
printf(“\n请输入a和b的值:”);
扫描频率(“%c”和“&x”);
扫描频率(“%c”和“y”);
printf(“\n交换前的值\na=%c\tb=%c”,x,y);
通用软件(
&x、 &y,
sizeof(char));//调用地址为x和y的swap函数
printf(“\n交换后的值\na=%c\tb=%c”,x,y);
打破
案例3://选择浮动操作的案例3
dataFloat=1;//表示已选择浮点操作
printf(“\n请输入a和b的值:”);
扫描(“%f%f”、&c和&d);
printf(“\n交换前的值\na=%.2f\tb=%.2f”,c,d);
通用软件(
&c、 &d,
sizeof(float));//调用地址为c和d的交换函数
printf(“\n交换后的值\na=%.2f\tb=%.2f”,c,d);
打破
案例0://终止应用程序
出口(1);
打破
默认值://未进行适当选择时
printf(“\n您输入了错误的选项”);
打破
}
}
}
//定义函数
void genericSwap(void*pdata1,void*pdata2,字节){
void*temp=NULL;//将void指针temp设置为NULL
temp=malloc(nBytes);//为无效指针分配内存
if(nBytes>1)//如果大小大于1字节,则表示它是另一个字节
//然后是一个字符
{
if(dataFloat==1)//如果dataFloat等于1,则它是浮点类型
{
dataFloat=0;//将dataFloat重置为0
*((float*)temp)=*((float*)pdata1);//键入将指针转换为float
*((浮动*)pdata1)=*((浮动*)pdata2);
*((浮动*)pdata2)=*((浮动*)温度);
}否则{
*((int*)temp)=*((int*)pdata1);//类型转换指向整数的指针
*((int*)pdata1)=*((int*)pdata2);
*((int*)pdata2)=*((int*)温度);
}
}否则{
*((char*)temp)=*((char*)pdata1);//键入指向字符的指针
*((char*)pdata1)=*((char*)pdata2);
*((字符*)pdata2)=*((字符*)温度);
}
空闲(临时);//取消分配内存
temp=NULL;//将指针temp设置为NULL
}
如果体系结构能够处理对32位或64位数据的未对齐访问,那么编译器很可能会优化对memcpy的调用

Cortex-M0要求数据对齐,而编译器没有优化memcpy


您可以将缓冲区设置为更大(在本例中为64字节),编译器还将生成非常高效的代码:

如果您确实不想分配动态内存,可以一次交换一个字节(或某个固定大小)。如果保证
nBytes
不会太大,另一个可能的选择是使用VLA(可变长度数组-例如,
uint8_t tmpArray[nBytes];
)。这有点危险,可移植性也有点差。但请注意,作为完整性的一个选项。不要过度思考这个问题。您正在交换两个内存区域(最好大小相同,这样才能工作)。使用两个无符号字符指针,同时迭代两个区域,一路上交换八位字节。更难的是:一旦您确定这是某种程度上,某种方式,您错误地认为需要修复的性能瓶颈的核心,请计算机器字边界,以便更有效地交换所讨论的大部分区域的数据。I如果它可用,您可以使用
alloca
在堆栈上分配内存。上面的代码不关心别名。这是一个值得注意的问题:即使是在循环和单字符交换时编写基本代码,人们也可能会惊讶地发现@WhozCraig的效果有多好。@WhozCraig它远没有效率。我们不希望每个字节都有分支来刷新管道e等@WhozCraig查看我的答案中的第二个示例:@WhozCraig-clang如果将您在内部循环中使用的对
memcpy
的三个调用内联,则会更好。
void *genericSwap(void *a, void *b, size_t size)
{
    uint64_t tmp;   //max size depends on the hardware architecture
    unsigned char *ua = a;
    unsigned char *ub = b;
    if(a && b)
    {
        while(size >= sizeof(tmp))
        {
            memcpy(&tmp, ua, sizeof(tmp));
            memcpy(ua, ub, sizeof(tmp));
            memcpy(ub, &tmp, sizeof(tmp));
            ua += sizeof(tmp);
            ub += sizeof(tmp);
            size -= sizeof(tmp);
        }
        while(size--) 
        {
            unsigned char tmp = *ua;
            *ua++ = *ub;
            *ub++ = tmp;
        }
    }
    return a;
}