C语言凯撒密码操作字符串指针时主调函数buffer值不更新问题
问题原因拆解
- 首先C语言的函数参数是值传递:你给encrypt函数传的是buffer指针的拷贝,函数内部对buffer指针本身的赋值(
buffer = (unsigned char *)temp_buffer;)只会修改这个局部拷贝的指向,完全不会影响main函数里的原buffer变量,所以外部看不到修改。 - 其次你直接用strcpy会段错误的原因:main函数里的buffer指向的是字符串常量,这类数据存放在进程的只读数据段,没有写入权限,直接往这个地址复制内容会触发内存访问违例。
另外你原有encrypt函数还存在两处隐藏bug:
malloc(strlen(buffer))少分配了1字节的空间,字符串末尾的'\0'没有地方存,会造成堆溢出。memset(temp_buffer, '\0', sizeof(temp_buffer))写法错误:temp_buffer是指针类型,sizeof(temp_buffer)拿到的是指针本身的大小(32位系统是4字节,64位是8字节),不是你申请的内存空间的总长度,初始化不完整。
可行解决方法
以下是三种常用的兼容实现方案:
方案1:函数返回加密后的字符串指针,主函数接收后使用、手动释放
#include <stdio.h> #include <stdint.h> #include <string.h> #include <stdlib.h> unsigned char* encrypt(unsigned char *src) { unsigned int i; size_t len = strlen(src); // 多分配1字节存结尾'\0' unsigned char *temp_buffer = (unsigned char *)malloc(len + 1); // 按申请的内存总长度初始化 memset(temp_buffer, '\0', len + 1); for(i = 0; i < len; i++) { temp_buffer[i] = src[i] + 2; } temp_buffer[len] = '\0'; printf("%s\n", temp_buffer); //输出加密后的内容 return temp_buffer; } int main() { unsigned char *src = "hello world"; printf("%s\n", src); //hello world unsigned char *encrypted = encrypt(src); printf("%s\n", encrypted); //输出预期的jgnnm"umpnf // 用完释放堆内存,避免内存泄漏 free(encrypted); return 0; }
方案2:传递二级指针,直接修改原指针的指向
如果不需要保留原字符串,可以用二级指针的方式,函数内部直接修改main函数里的指针指向:
#include <stdio.h> #include <stdint.h> #include <string.h> #include <stdlib.h> int encrypt(unsigned char **buffer) { unsigned char *src = *buffer; unsigned int i; size_t len = strlen(src); unsigned char *temp_buffer = (unsigned char *)malloc(len + 1); memset(temp_buffer, '\0', len + 1); for(i = 0; i < len; i++) { temp_buffer[i] = src[i] + 2; } temp_buffer[len] = '\0'; printf("%s\n", temp_buffer); // 修改原指针的指向,指向新申请的加密内存 *buffer = temp_buffer; return 0; } int main() { unsigned char *buffer = "hello world"; printf("%s\n", buffer); //hello world encrypt(&buffer); printf("%s\n", buffer); //输出预期的加密内容 free(buffer); //记得释放堆内存 return 0; }
方案3:主函数提前分配可写缓冲区,传进去直接修改
如果不想手动管理堆内存,也可以在主函数开栈上的可写数组,把数组地址传进去,函数内部直接修改数组内容即可:
#include <stdio.h> #include <stdint.h> #include <string.h> #include <stdlib.h> int encrypt(unsigned char *buffer, size_t buf_len) { unsigned int i; // 直接在传入的可写缓冲区上修改 for(i = 0; i < buf_len && buffer[i] != '\0'; i++) { buffer[i] = buffer[i] + 2; } printf("%s\n", buffer); return 0; } int main() { // 开栈上的可写数组,初始化内容为hello world unsigned char buffer[32] = "hello world"; printf("%s\n", buffer); //hello world encrypt(buffer, sizeof(buffer)); printf("%s\n", buffer); //输出预期的加密内容 // 栈内存会自动回收,不需要手动释放 return 0; }
内容的提问来源于stack exchange,提问作者dehils19
相关产品推荐
相关产品推荐

