如何在不使用malloc的情况下实现MicroJSON式字符串拷贝及数组赋值?
无malloc的C字符串拷贝实现及字符串数组赋值问题
背景
我在MicroJSON的仓库页面看到,它的代码可以将JSON解析到静态C结构体且无需使用malloc(3)。我查看了其源码片段(如下),但不确定是否理解正确:
char *lptr; switch (cursor->type) { case t_integer: memcpy(lptr, &cursor->dflt.integer, sizeof(int)); }
我尝试实现无malloc的字符串拷贝,先后写出如下代码:
首次尝试
char json[] = "{\"name\": \"john\"}" char *copy = NULL; memcpy(copy, 9, 4); // john starts at 9 and has 4 characters length
二次尝试(可运行)
char *substring(const char *start, long len, char *destination) { strncpy(destination, start, len); destination[len] = '\0'; return destination; } char key[5]; substring(9, 4, key);
问题咨询
- 如何正确实现无malloc的字符串拷贝?
- 能否在不使用malloc的情况下,将长字符串的不同部分作为项赋值给字符串数组?
问题解答
1. 正确实现无malloc的字符串拷贝
无malloc的核心是提前分配好足够的内存空间(比如栈上数组、静态数组或全局数组),绝对不能用空指针直接作为拷贝目标(你的首次尝试就犯了这个错误,copy是NULL,没有指向有效内存区域)。
你的二次尝试方向是对的,但存在参数传递错误:调用substring时传的9是数值,不是字符串指针,应该改成json + 9来指向"john"的起始位置。修正后的代码如下:
char *substring(const char *start, long len, char *destination) { // 先做合法性检查,避免非法内存访问 if (destination == NULL || start == NULL) return NULL; // 已知长度的情况下,memcpy比strncpy效率更高 memcpy(destination, start, len); // 手动添加字符串终止符,确保是合法的C字符串 destination[len] = '\0'; return destination; } char json[] = "{\"name\": \"john\"}"; char key[5]; // 指向json中"john"的起始索引位置 substring(json + 9, 4, key);
注意要点:
- 必须保证
destination指向的内存空间至少有len+1个字节(要预留存储终止符\0的位置),否则会触发缓冲区溢出。 - 一定要手动添加
\0:memcpy不会自动添加终止符,strncpy在拷贝长度耗尽时也不会添加,必须自行处理。
2. 无malloc实现长字符串不同部分赋值给字符串数组
完全可以实现,核心思路和字符串拷贝一致:提前为数组的每个元素分配固定大小的内存空间,再将长字符串的对应部分拷贝进去。
举个实际示例,从JSON字符串中提取多个字段存入字符串数组:
#include <stdio.h> #include <string.h> char *substring(const char *start, long len, char *destination) { if (destination == NULL || start == NULL) return NULL; memcpy(destination, start, len); destination[len] = '\0'; return destination; } int main() { char json[] = "{\"name\": \"john\", \"age\": \"30\", \"city\": \"nyc\"}"; // 提前定义字符串数组,每个元素分配足够空间(这里设为最多存10个字符+1个终止符) char str_array[3][11]; // 提取"john"(起始索引9,长度4) substring(json + 9, 4, str_array[0]); // 提取"30"(起始索引20,长度2) substring(json + 20, 2, str_array[1]); // 提取"nyc"(起始索引32,长度3) substring(json + 32, 3, str_array[2]); // 打印结果 for (int i = 0; i < 3; i++) { printf("str_array[%d] = %s\n", i, str_array[i]); } return 0; }
如果字段长度不确定,可以:
- 先解析出每个字段的长度,确保数组元素的空间足够覆盖(比如定义一个足够大的固定长度,比如256字节,适配业务场景即可)。
- 若数组规模较大,优先使用全局数组或静态数组,避免栈空间溢出(栈空间通常较小,大数组放在全局区/静态区更安全)。
另外还有一种思路:不拷贝内容,直接用指针指向长字符串的对应位置。但这种方式要求原字符串的生命周期必须长于指针,且原字符串不能被修改(否则指针指向的内容会同步变化),同时只有当原字符串的目标片段本身以\0结尾时才适用,否则还是拷贝方式更安全。
内容的提问来源于stack exchange,提问作者Source
相关产品推荐
相关产品推荐

