C语言数组初始化与指针实现数组拷贝的相关技术疑问
嘿,咱们一步步来解决你的两个问题,先把核心概念理清楚:
int my_array[] = {0};中编译器如何确定数组大小? 首先纠正一个小笔误:你写的int my_array = {0};是语法错误,正确写法应该是int my_array[] = {0};(必须加上方括号)。
回到你的问题:当你声明数组时不指定大小,但提供初始化列表,编译器会直接根据初始化列表里的元素个数确定数组长度。这里你的初始化列表只有一个0,所以编译器会把数组大小设为1,等价于int my_array[1] = {0};。
至于你提到的0和'\0'等价——要注意它们只是数值相同(都是0),但语义完全不一样:在这个int数组里,0就是普通的int类型数值,编译器根本不会把它当成字符串的“空终止符”处理,它判断数组大小的唯一依据是初始化列表的元素数量,和元素的值无关。
先看你代码里的几个核心问题:
终止条件逻辑错误
你用*ptr1 != '\0'判断源数组结束,但'\0'是char类型的空字符,虽然数值是0,但你的源数组是int类型——如果源数组里本来就有合法的int 0元素,拷贝会提前终止;更关键的是,当你用int dest_array[10] = {0};初始化目标数组时,所有元素都会被设为int类型的0,你的判断if(!*ptr2)会在第一次循环就触发(因为*ptr2一开始就是0),直接中断拷贝,这就是功能失效的原因。数组传参的本质误区
你已经意识到“无法用sizeof比较数组大小”,再明确一下:当你把数组作为参数传递给函数时,它会自动退化为指向数组第一个元素的指针。所以在函数内部,sizeof(src_arr)或sizeof(dest_arr)返回的是指针的大小(比如32位系统是4字节,64位是8字节),根本拿不到数组的实际长度或容量。
怎么解决这个问题?
给你几个实用的方案:
- 显式传递数组大小(最推荐)
这是最安全、最通用的方式,直接把源数组的长度和目标数组的容量作为参数传给函数,完全不用依赖元素的值判断:
#include <stdio.h> #include <stddef.h> // 用于size_t类型 void copy(int *src_arr, size_t src_len, int *dest_arr, size_t dest_cap) { // 计算实际能拷贝的元素数量:取源数组长度和目标容量的较小值 size_t copy_count = (src_len < dest_cap) ? src_len : dest_cap; for (size_t i = 0; i < copy_count; i++) { dest_arr[i] = src_arr[i]; } if (src_len > dest_cap) { printf("Copy interrupted: Destination array is too small\n"); } } // 调用示例: // int src[] = {1,2,3,4,5}; // int dest[3] = {0}; // copy(src, 5, dest, 3);
用哨兵值(局限性大)
如果你一定要模仿字符串的'\0'逻辑,必须选一个绝对不会出现在源数组合法元素里的特殊值当哨兵(比如如果你的数组里不会用到INT_MIN,可以用它)。但这种方式风险很高,一旦源数组出现这个值,拷贝就会提前终止,只适合非常特定的场景。用结构体包裹数组(繁琐但可行)
把数组和它的大小打包成结构体,这样传递结构体时不会退化,能直接拿到数组信息,但写法比较繁琐,一般不推荐日常使用:
#include <stdio.h> typedef struct { int data[100]; size_t len; } IntArray; void copy_array(IntArray *src, IntArray *dest) { size_t copy_count = (src->len < 100) ? src->len : 100; // 假设dest的容量是100 for (size_t i = 0; i < copy_count; i++) { dest->data[i] = src->data[i]; } dest->len = copy_count; if (src->len > 100) { printf("Copy interrupted: Destination array is too small\n"); } }
最后划个重点:
int数组里的0就是普通数值,和字符'\0'只是数值相同,语义完全不同——不能用它来判断数组的结束或大小;数组传参必然退化为指针,所以必须显式传递大小,或者用其他方式携带数组的长度信息。
内容的提问来源于stack exchange,提问作者cassepipe

