如何用strcpy从目标数组指定索引复制数组?结构体复制编译警告排查
strcpy()从目标数组指定索引开始复制 咱们先搞懂strcpy()的本质:它是从指定的内存起始地址开始,把源字符串(包括末尾的'\0')完完整整复制过去。所以要从destination_array的指定索引start_idx开始复制,本质就是把strcpy的目标地址指向那个索引对应的位置就行,有两种写法都能用:
strcpy(&destination_array[start_idx], array_src);strcpy(destination_array + start_idx, array_src);
但这里有几个坑你绝对要避开:
- 必须保证
destination_array从start_idx开始的剩余空间,足够装下array_src的所有内容(包括那个终止符'\0'),不然会触发缓冲区溢出,这属于未定义行为,搞不好程序直接崩掉。 start_idx得是合法索引,不能超出destination_array的范围(比如数组长度是15,start_idx就不能大于等于15)。- 如果
array_src不是以'\0'结尾的字符串(比如是存二进制数据的普通字符数组),别用strcpy!直接换memcpy更安全,因为strcpy会一直读内存直到找到'\0',很容易越界。
给你整个简单的示例代码感受下:
#include <string.h> #include <stdio.h> int main() { char array_src[] = "World"; char destination_array[20] = "Hello, "; // 初始内容是"Hello, \0..." int start_idx = 7; // 从逗号后面的位置开始复制 strcpy(destination_array + start_idx, array_src); printf("%s\n", destination_array); // 输出:Hello, World return 0; }
先理清楚你的需求:把temp_array复制到pointer2->opcode_CHAR的j位置,其中j = 6 - sizeof(temp_array)。我先给你拆解常见的警告原因,再给对应的解决办法:
先明确几个核心点:
sizeof(temp_array)是编译时就确定的常量,所以j也是固定值,比如temp_array是char[4],j=2;char[2]的话j=4,这个逻辑本身没问题。- 如果你要复制的是纯字符数组(不是字符串,没有
'\0'),绝对别用strcpy!这几乎是触发警告的最常见原因——strcpy是专门处理字符串的,它会一直复制到'\0',如果temp_array没有这个终止符,就会越界读内存,编译器会直接给你抛警告,甚至程序运行时出问题。
常见警告原因&解决办法:
原因1:用strcpy处理非字符串数组
如果temp_array是用来存 opcode 这类无终止符的字符数组,用strcpy会触发类似passing argument ... makes pointer from integer或者potential buffer overflow的警告。
解决办法:换成memcpy,它专门用来复制指定长度的内存块,完美匹配你的需求:
#include <string.h> // 先把结构体和变量声明写清楚 struct node { char opcode_CHAR[6]; }; int main() { // 注意:pointer2必须指向一个有效的node实例,别搞野指针! struct node my_node; struct node *pointer2 = &my_node; char temp_array[4]; // 示例:sizeof=4,j=6-4=2 // 假设这里给temp_array赋值了,比如temp_array[0] = 'A'; 等等 int j = 6 - sizeof(temp_array); // 复制temp_array的所有内容到opcode_CHAR的j位置 memcpy(pointer2->opcode_CHAR + j, temp_array, sizeof(temp_array)); return 0; }
原因2:pointer2是野指针
如果pointer2没初始化(比如直接声明struct node *pointer2;但没指向任何有效的节点),编译器会触发dereferencing uninitialized pointer这类警告。这时候你得给它找个合法的节点:
// 方案1:指向栈上的节点(简单直接) struct node my_node; struct node *pointer2 = &my_node; // 方案2:动态分配内存(适合需要长期存在的节点) struct node *pointer2 = malloc(sizeof(struct node)); if (pointer2 == NULL) { // 处理内存分配失败的情况,比如打印错误信息 perror("malloc failed"); return 1; }
原因3:数组越界风险
如果sizeof(temp_array) > 6,那j会是负数,这时候pointer2->opcode_CHAR + j会指向数组外面的内存,编译器会触发array index is negative或者out of bounds的警告。你可以加个编译时断言来提前检查:
#include <assert.h> // 编译时就检查temp_array的大小不能超过6,超了直接报错 _Static_assert(sizeof(temp_array) <= 6, "temp_array size is too big for opcode_CHAR");
最后再提个容易写错的点
目标地址一定要写pointer2->opcode_CHAR + j(或者&pointer2->opcode_CHAR[j]),别写成pointer2 + j——那是结构体指针的偏移,不是数组索引的偏移,会导致类型不匹配的警告,完全不是你想要的效果。
内容的提问来源于stack exchange,提问作者topcat

