int array[ 5 ];
接着,只需设置一个对象:
array[ 0 ] = 7;
如何检查其他键(array[1]
,array[2]
,...)是否存储了值?(在这种情况下,它们当然没有。)
是否有像PHP的isset()
函数一样的功能?
if ( isset(array[ 1 ]) ) ...
C语言中不存在这样的东西。静态数组的内容总是“设置”的。但是,您可以填充一些特殊值来假装它未初始化,例如:
// make sure this value isn't really used.
#define UNINITIALIZED 0xcdcdcdcd
int array[5] = {UNINITIALIZED, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED};
array[0] = 7;
if (array[1] != UNINITIALIZED) {
...
你不能这样做
这些值都是未定义的(因此随机的)。
你可以显式地将所有值归零,以便至少有一个良好的起点。但使用魔数来检测对象是否已初始化被认为是不好的实践(但初始化变量被认为是好的实践)。
int array[ 5 ] = {};
但是,如果您想明确检查它们是否已经在创建时明确设置(而不使用魔数),则需要将该信息存储在另一个结构中。
int array[ 5 ] = {}; // Init all to 0
int isSet[ 5 ] = {}; // Init all to 0 (false)
int getVal(int index) {return array[index];}
int isSet(int index) {return isSet[index];}
void setVal(int index,int val) {array[index] = val; isSet[index] = 1; }
memset
无法使用 INT_MIN
进行填充。它只能填充字节。 - R.. GitHub STOP HELPING ICEINT_MIN
是 ~0
,并且会用 -1
填充 int[]
的所有元素。 - stragerINT_MIN
只是 ~0
,这种类型很少见,实际上可能根本不存在。在大多数系统(二进制补码),~0==-1
。 - R.. GitHub STOP HELPING ICE我不了解php,但这里可能有两种情况:
在任何情况下,对于数组的值来说,“未设置”都是一个有意义的概念。另一方面,内置类型的c数组始终在每个单元格中具有“某些”值。如果数组未初始化且为自动或在堆上分配,则这些值可能是随机的,但它们存在。
要获得php行为:
一个解决方案也许是使用一个单独的标志数组。当你赋值其中一个元素时,设置布尔数组中的标志。
你也可以使用指针。你可以使用空指针来表示尚未分配的数据。我在下面举例说明:
int * p_array[3] = {NULL,NULL,NULL};
p_array[0] = malloc(sizeof(int));
*p_array[0] = (int)0;
p_array[2] = malloc(sizeof(int));
*p_array[2] = (int)4;
for (int x = 0; x < 3; x++) {
if (p_array[x] != NULL) {
printf("Element at %i is assigned and the value is %i\n",x,*p_array[x]);
}else{
printf("Element at %i is not assigned.\n",x);
}
}
我喜欢的一种方法是创建两个数组,一个是位数组,标记数组中哪些索引已设置,另一个包含实际值。即使在您不需要知道数组中的项目是否“设置”的情况下,它也可以是有用的优化。将每个元素的1位比特位清零比初始化每个元素的8字节大小的size_t
数组要快得多,特别是如果数组在其整个生命周期内仍然稀疏(大部分未填充)。
我使用这个技巧的一个实际例子是在子字符串搜索函数中,使用Boyer-Moore风格的坏字符跳过表。该表需要256个size_t
类型的条目,但只需要填充与实际出现在针线中的字符相对应的条目。在非常短的搜索情况下,1kb(或64位上的2kb)的memset
会占用CPU使用率,导致其他实现在是否使用表时进行启发式处理。但是,我让跳过表未初始化,并使用256位位数组(只有32字节要提供给memset
)来标记使用哪些条目。