C 我的Int*数组是否全部初始化为NULL?
我是一个努力理解C指针和数组的Java程序员。充分披露:我也是一名CS学生,是的,这个问题帮助我完成一项编程作业 我试图创建一个int*指针数组,然后确保每个指针都为NULL。稍后,当我需要在数组中查找数据时,这将发挥作用;给定的点中是否有有效的int或NULL将非常重要 因此为数组分配空间很容易,但是如何将所有这些指针设置为NULL呢?以下是我的一次不太成功的尝试:C 我的Int*数组是否全部初始化为NULL?,c,arrays,pointers,initialization,C,Arrays,Pointers,Initialization,我是一个努力理解C指针和数组的Java程序员。充分披露:我也是一名CS学生,是的,这个问题帮助我完成一项编程作业 我试图创建一个int*指针数组,然后确保每个指针都为NULL。稍后,当我需要在数组中查找数据时,这将发挥作用;给定的点中是否有有效的int或NULL将非常重要 因此为数组分配空间很容易,但是如何将所有这些指针设置为NULL呢?以下是我的一次不太成功的尝试: #include<stdio.h> #include<stdlib.h> #define TABLES
#include<stdio.h>
#include<stdlib.h>
#define TABLESIZE 10
int main(int argc, char *argv[]){
int* table = (int*) malloc(TABLESIZE * sizeof(int));
// Initialize all *int pointers to NULL
int i;
for(i=0; i<TABLESIZE; i++){
if((table+i)!=NULL){ // They may be NULL already? I don't know...
*(table+i) = NULL; // This generates a warning:
// "warning: assignment makes integer from pointer without a cast [-Wint-conversion]"
}
}
// Sanity check : are all int* are NULL ?
for(i=0; i<TABLESIZE; i++){
printf("%d: %p %d ", i, (table+i), *(table+i));
if((table+i) == NULL)
printf("(NULL)");
printf("\n");
}
free(table);
return 1;
}
所以我会坦率地说。。。我不知道上面告诉我什么。我猜我已经创建了一个1D数组,数组中的所有值都是有效的整数,都是0
但在我的程序中,这是有问题的。当我的代码需要将数据插入表[x]时,代码必须能够查看数组,并知道以前是否在同一位置插入了另一个有效的int。如果它看到表[x]=0,它是否认为索引x中插入了0,或者spot可用
我喜欢使用指向int的指针数组的想法,因为这样可以很好地解决这个问题。如果我的代码看到:
table[x] --> NULL // This spot is empty and available
table[x] --> 0 // This spot is occupied, can't insert here
表[x]->NULL//此点为空且可用
表[x]->0//此位置已被占用,无法在此插入
但我不认为我在编码我想要的
非常感谢您的任何想法/建议/评论/批评
谢谢!
-皮特
不创建指针数组,而是创建单个int指针,指向大小为TABLESIZE*sizeofint的已分配内存块的开头
得到错误的原因是int*就是这个;指向int的指针
*运算符称为“取消引用”运算符。当它放在一个变量之前时,它的作用是说“转到这个指针指向的任何地方”。因此,该行
*(table+i) = NULL;
意思是“转到表指向的任何地方,沿着i*sizeofint移动,然后将特定int设置为NULL。这显然没有意义-不能将int设置为NULL,因为这是指针值。这就是你的错误
顺便说一句,由于指针也可以像C中的数组一样处理,所以上面这一行也是
如果希望初始malloc是指针数组,则需要为int*分配空间,而不是为int*分配空间,这样就可以了
int** table = malloc(TABLESIZE * sizeof(int*));
然后有一个int**双指针,也就是指向引用TABLESIZE int*块的指针的指针
完成此操作后,该行下面的代码将正确地将指针设置为NULL。然后,为了实现问题中所述的表,在将int放入每个单元格之前,需要对每个单元格执行进一步的malloc。例如,将“3”放入单元格2中
if(*(table + 2) == NULL) {
*(table + 2) = malloc(sizeof(int));
}
**(table + 2) = 3;
注意最后一行的双重区别:“转到表指向的任何地方,沿着2*sizeofint*移动,然后转到指针指向的任何地方。”同样,这也可以通过数组语法实现
if(table[2] == NULL) {
table[2] = malloc(sizeof(int));
}
*table[2] = 3;
注意不要在同一个单元上调用malloc两次;如果你这样做,你将有一个内存泄漏
我是一个努力理解C指针和数组的Java程序员
是的,代码中的挣扎部分是显而易见的
C数组只是指定类型元素的有序集合,在内存中连续排列。这类似于Java数组,但Java不提供任何方法让您查看或探测内存中元素的排列,而且它的数组具有与元素相关的附加数据,特别是它们知道自己的长度
C指针是一个表示其他对象地址的值,其中对象表示任何类型的存储值,包括内置Java:基元类型、聚合类型、结构和数组、指针类型,甚至没有特定类型。这在某些方面与Java引用类似,这反映在一个事实上,即如果Java试图取消对空引用的引用,它会引发NullPointerException
非常重要的是要理解,尽管数组和指针之间有着密切的关系,但它们根本不是一回事。从上面的描述中可以清楚地看到这一点,但我经常会遇到相反的无厘头的说法
理解指针值可能无效也很重要-不指向任何对象。您可以很容易地拥有一个指针值,它可能存储在变量或数组中,其值是垃圾。这是需要管理的,不必害怕
此外,理解指针值不一定必须通过内存分配函数获得是很重要的。它们也可以通过操作符的地址获得&或者通过对涉及数组的表达式求值获得,或者在声明指针但未初始化指针时,垃圾指针值可以自然出现
我试图创建一个int*指针数组
我不确定你指的是一个数组,它的元素
e type int*pointer to int,一个数组,其元素的类型为int**pointer to pointer to int,或者可能是一个数组,其元素的类型为int。我从您的措辞中猜测是第一个,从字面上看您会产生第二个,而您的实际代码呈现类似于第三个的内容
这将是int*数组的声明:
没有指定初始值设定项,在赋值之前,不能依赖元素的任何特定值。与您介绍的代码类似的代码可以用于减少空检查,空检查由于初始值不确定而具有未定义的行为,并且无论如何都不会提供任何优势,但我倾向于编写稍微不同的代码:
for (int i = 0; i < TABLESIZE; i++) {
table[i] = NULL;
}
这没有意义,因为被解释为任何指针类型的值的0是空指针常量。但是,首先将表的所有元素分配为NULL,如果在分配元素时要将元素设置为有效指针,则可以检查NULL以查看点是否可用,因为NULL从来不是指向对象的指针
顺便说一句,请注意,如果您将表声明为真正的数组(如上所述),则不需要释放它。但是,您可能需要释放其元素所指向的部分或全部对象,这取决于这些对象是否被动态分配,以及它们是否已经或将通过其他方式被释放。在C和Java中,int都包含一个整数值。没有其他可区分的空状态。通常,int的每一个可能的位模式都代表一个不同的整数值,因此物理上不可能存储这个额外的状态
如果要实现可以是“null”或int范围内的任何可能值的内容,则必须为每个数组项使用额外的存储。例如,您可以维护一组并行的布尔标志,指示每个条目是否处于活动状态
另一种解决方案是保留一个特定的整数值,以表示该数组项应视为空。这种技术称为哨兵值
在Java中,可以有一个Integer数组,它是一个引用数组,可以为null,也可以引用存储在其他地方的int。语言在幕后管理分配。用C语言模拟内存布局
守则是:
// Allocate array and initialize all entries to NULL
int * array[ARRAYSIZE] = { NULL };
// Insert at position (repeatable)
if ( array[2] == NULL )
array[2] = malloc( sizeof(int) );
*array[2] = 10;
// Use item
printf("%d\n", *array[2]);
// Remove from position
free( array[2] );
array[2] = NULL;
为了避免内存泄漏,您需要记住在数组超出范围之前循环并执行删除过程。检查malloc故障并中止程序或采取其他措施也很好
请注意,这种技术在C语言中被认为是不寻常的,而且与其他可用选项相比不节省空间。@merl:这是胡说八道!通常,NULL'是定义NULL void*0`。为了便于文档编制/可读性,建议使用宏。此外,空指针不需要具有全部零的位表示形式。表[x]不是指针,而是int。因此,将其赋值为null是没有意义的。@merl:在启用了现代编译器和警告的情况下,通过比较void*和int,您将得到一个类型missmatch警告。更不用说指针类型和整数之间的转换是由实现定义的,在许多系统上都会产生差异/问题。目前还不清楚OP真正需要什么@Olaf你是对的,我想说的是OP不能用0和NULL来区分整数。@KeithThompson sizeof*表对于不习惯这个的人来说似乎太模糊了。不要播放malloc和friends的返回,这被认为是有害的。它是C++所需要的,但在C@BenWainwright:指针显然存在,但未锁定对象并分配该地址。我的参考是C标准。总是一本好书。我也知道C语言。你混淆了对象和指向它的指针。顺便说一句,由于指针也可以像C中的数组一样对待,在这种通用形式下,它至少是误导性的。对指针引用的对象的访问可以通过将指针声明为数组来完成。这就是全部。数组和指针之间有着巨大的根本区别。不要混淆OP,@AminNegm Awad。int*table=NULL;不生成指向NULL的指针-它创建指针类型的变量,其值(而不是其referent)为NULL。例如,一个空指针。@BenWainwright谢谢Ben,这太好了。解释得很清楚啊。你回答的第二部分对OP想要做什么给出了一个非常合理的解释。我有足够的Java背景,有点不好意思我没有想到这一点。@M.M这太棒了,谢谢你花时间来阐述这一点。我已经把这个抄到我的笔记里了int*数组[ARRAYSIZE]={NULL};仅将第一个元素初始化为NULL所有其他元素都初始化为二进制0,这不一定需要导致数组的元素携带NULL。虽然C标准统计
表示char*p=0;和char p=NULL比较应相等,NULL不一定需要用二进制0表示。由此派生:如果数组[2]==NULL可能会失败。@alk no,它实际上会生成NULL指针。见C11 6.7.9/21和/10@M.M:我站着纠正。我不知怎的错过了6.7.9/21明确提到的*/10。谢谢你给我指这个。我似乎把这个和实际情况混淆了:memsetarray,0,sizeof array;谢谢你,约翰,这是有道理的。我有点挫伤地了解到C语法比我预想的要复杂得多。这对清理东西有很大帮助
int *table[TABLESIZE];
for (int i = 0; i < TABLESIZE; i++) {
table[i] = NULL;
}
// Sanity check : are all int* are NULL ?
for(int i = 0; i < TABLESIZE; i++) {
printf("%d: %p ", i, (void *) table[i]);
if(table[i] == NULL)
printf("(NULL)");
printf("\n");
}
table[x] --> NULL // This spot is empty and available
table[x] --> 0 // This spot is occupied, can't insert here
// Allocate array and initialize all entries to NULL
int * array[ARRAYSIZE] = { NULL };
// Insert at position (repeatable)
if ( array[2] == NULL )
array[2] = malloc( sizeof(int) );
*array[2] = 10;
// Use item
printf("%d\n", *array[2]);
// Remove from position
free( array[2] );
array[2] = NULL;