C 如何使指针==null测试通过?

C 如何使指针==null测试通过?,c,pointers,struct,C,Pointers,Struct,这是我的密码 struct customer_account { char login[20]; char password[20]; int balance; }; typdef struct customer_account Account; int main(int argc, char *argv[]) { Account *allUsers; allUsers = (Account *) calloc(3, sizeof(

这是我的密码

struct customer_account {
      char login[20];
      char password[20];
      int balance;
};
typdef struct customer_account Account;
int main(int argc, char *argv[]) {
      Account *allUsers;  
      allUsers = (Account *) calloc(3, sizeof(Account));
      *allUsers = (Account) {"Ann", "nna", 100);
      *(allUsers + 1) = (Account) {"Beth", "hteb", 200};
      *(allUsers + 2) = (Account) {"Carl", "lrac", 500};
      printf("%p\n", allUsers + 3);
      printf("%d\n", (allUsers + 3) == NULL);
}
当我运行程序时,这里是我得到的输出(不理解指针值的意义,没有真正研究十六进制)


据我所知,我所做的是请求足够的内存来存储操作系统中的3个帐户结构(我稍后会释放它),指针allUsers可以用来存储我从动态分配中获得的第一个帐户结构的地址,我可以通过指针算法访问其余的帐户结构。我的问题来自我的代码,因为只有3个帐户结构,(allUsers+3)不应该计算为null吗?有没有办法使(allUsers+3)的计算结果为空?我在那里的测试评估为0,错误。

alluser+3
表示从分配给
alluser
的地址开始的第四个
struct customer\u账户
。它在任何情况下都不可能为空。这和

&allUsers[3]
它的内容可以归零,但指针本身是有效指针的正偏移量,标准要求它为非NULL,因为它比动态分配的数组的末尾多了一个字节

要了解发生了什么,请进行以下实验:

for (int i = 0 ; i != 4 ; i++) {
    printf("%p\n", (void*)(allUsers + i));
}

这将打印四个数字-第一个是
allUsers
,第二个是
allUsers
加上一个
struct customer\u账户的大小,第三个是
allUsers
加上两个
struct customer\u账户的大小,最后一个是程序打印的内容。如您所见,这些地址是简单计算的结果,与实际数组的内容无关。

allUsers是指向内存中地址的指针。 如果n>0,则allUsers+n是指向更高地址的指针


allUsers和所有其他地址都不知道您使用malloc分配了多少内存。您需要自己跟踪它,或者在单独的变量中,或者通过为具有某些特殊终止值的元素分配额外的空间。

不应该(allUsers+3)计算为null
-只有当
allUsers
为-3时。撇开玩笑不谈:内存分配不是这样工作的。还有指针算法。内存在分配和释放时不会被“创建”或“销毁”。它只是保留或不保留供您的程序使用。指针,作为第一近似值,只是一个巨大的全局字节数组的索引,称为内存。@TheParamagneticCroissant,不应该是-3*(sizeof(Account))?@lee或者完全不相关,那是。这取决于你们如何解释指针算法(但由于这已经是一个毫无意义和不可能的情况,我不想进一步讨论这个问题),你们能解释下票数吗?我认为这是一个很好的问题,有很好的代码示例。@ParamagneticCroissant和那个巨大的全局字节数组是堆,对吗?因为这就是可以动态分配的内存所在。为什么要将指针强制转换为void*?我知道%p是指针的格式说明符。@CommittedDroider不是“指针”的格式说明符。它用于
void*
。(-请参阅“参数类型”列)@committeedandroider
%p
不仅仅是一个指针,它是指向
void
的指针(请参阅)。Standard说,
char*
将具有与
void*
相同的布局,但是当您将其传递给
%p
时,指向其他任何内容的指针都需要转换为
void*
。请注意,“有效指针的正偏移量”仅对仍在分配数组中的偏移量(或超过其末尾的偏移量)才有意义-其他任何东西都会导致未定义的行为,因此
allusers+4==NULL
有机会比较trueYeah谢谢。我想我应该保留一个int变量来保存我需要的帐户数。
for (int i = 0 ; i != 4 ; i++) {
    printf("%p\n", (void*)(allUsers + i));
}