我有以下代码。我知道这是错误的,但问题是我不明白为什么。下面我解释一下我的疑问。
#include <stdio.h>
struct mychar {
char value;
struct mychar *nextPtr;
};
typedef struct mychar Mychar;
void insert(Mychar **, char ); // line 19
void printlist(Mychar **);
int main(){
Mychar *startPtr = NULL;
insert(&startPtr, 'b');
printlist(&startPtr);
}
void insert(Mychar **sPtr, char myvalue){
Mychar *newlinkPtr = calloc(1, sizeof(Mychar));
if (**sPtr == NULL){ // if I put two ** I get errors
newlinkPtr->value = myvalue;
newlinkPtr->nextPtr = **sPtr; // same here
**sPtr = newlinkPtr; // same here
}
}
void printlist(Mychar **startPtr){
printf("%cn", *startPtr->value); // get error
}
以下是错误:
liste_collegate.c:29:13: error: invalid operands to binary expression ('Mychar' (aka 'struct mychar') and 'void *')
if (**sPtr == NULL){
~~~~~~ ^ ~~~~
liste_collegate.c:31:23: error: assigning to 'struct mychar *' from incompatible type 'Mychar' (aka 'struct mychar'); remove *
newlinkPtr->nextPtr = **sPtr;
^ ~~~~~~
liste_collegate.c:32:10: error: assigning to 'Mychar' (aka 'struct mychar') from incompatible type 'Mychar *' (aka 'struct mychar *'); dereference with *
**sPtr = newlinkPtr;
^ ~~~~~~~~~~
*
liste_collegate.c:38:26: error: member reference base type 'Mychar *' (aka 'struct mychar *') is not a structure or union
printf("%cn", *startPtr->value);
我的疑问:
- 为什么如果在函数
insert
参数中我写**sPtr
,那么在if块中我必须使用*sPtr
,否则它会给我错误?**sPtr
不等于 NULL,因为我主要在其中输入了 NULL 值?在main()
中,当我在第 19 行调用insert
时,我向那里发送了startPtr
的地址和,所以要在insert
函数中访问其值 NULL,我应该放一个*
来实际到达指针,另一个*
来实际到达 NULL 值。 - 在
printlist
功能上,几乎与以前的疑问相同。如果我"发送"以printlist
链表第一个指针的地址,以实际访问第一个结构,我不应该取消引用以实际到达结构地址,然后再次取消引用->
以控制该结构的指针以获取"值"?
首先是你的insert
函数:
void insert(Mychar **sPtr, char myvalue){
Mychar *newlinkPtr = calloc(1, sizeof(Mychar));
if (**sPtr == NULL){ // if I put two ** I get errors
newlinkPtr->value = myvalue;
newlinkPtr->nextPtr = **sPtr; // same here
**sPtr = newlinkPtr; // same here
}
}
sPtr
的类型Mychar **
:指向指针的指针。
*sPtr
的类型Mychar *
:指向类型Mychar
的指针。
现在,当您使用**sPtr
时,类型为Mychar
:类型为Mychar
的值。
NULL
用于指针而不是值。因此,如果要比较,可以将sPtr
与NULL
进行比较,也可以将*sptr
与NULL
进行比较。不应将值**sPtr
与NULL
进行比较。顺便说一句,你的函数可以变成:
void insert(Mychar **sPtr, char myvalue){
Mychar *newlinkPtr = calloc(1, sizeof(Mychar));
if (!newlinkPtr) {return;} // you should check the return value of calloc funciton because it may be failed
if (*sPtr == NULL) {
newlinkPtr->value = myvalue;
newlinkPtr->nextPtr = *sPtr;
*sPtr = newlinkPtr;
}
}
对于打印功能:
void printlist(Mychar **startPtr){
printf("%cn", *startPtr->value); // get error
}
*startPtr->value
应该更改为(*startPtr)->value
.
但是,使用打印功能,您不需要使用指向指针的指针,因为在此函数中,您无需更改或更新任何内容。您可以将指针用作:
void printlist(Mychar *startPtr){
printf("%cn", startPtr->value);
}
如果你这样做,在主函数中,当你调用打印函数时:
printlist(startPtr);
"既然我把
NULL
值放在里面,**sPtr
不等于NULL
吗?">
不。
NULL
是空指针的宏;它仅用于指针,而不是引用的对象(除非引用的对象也是指针并且您想检查是否为NULL
,但这不是这里的重点(。
**sPtr
是一个指向类型Mychar
的指针,实际上是一个结构体。如果你取消引用sPtr
(表示*sPtr
(,你访问它指向的指针(实际上是在main中startPtr
(,这对于检查NULL
是正确的。
如果您使用if (**sPtr == NULL)
则尝试取消引用startPtr
- 一个NULL
指针 - 本身,这是无效的,并尝试检查startPtr
指向的对象(实际上没有任何对象(是否NULL
,但不是startPtr
。
"我不应该取消引用以实际到达结构地址,然后再次取消引用
->
以控制该结构的指针以获取"值"吗?">
您需要先取消引用指向指针startPtr
的指针,然后通过->
取消引用访问value
。请改用(*startPtr)->value)
。
旁注:
- 如果分配成功,请始终检查内存管理函数的返回值。
F.e.:
Mychar *newlinkPtr = calloc(1, sizeof(Mychar));
if (newlinkPtr == NULL)
{
fputs("Allocation failed!", stderr);
exit(1);
}
- (可能只是一个复制和粘贴错误,但值得一提( - 你忘了
#include <stdlib.h>
,这是使用calloc()
所必需的。
结果:
#include <stdio.h>
#include <stdlib.h>
struct mychar {
char value;
struct mychar *nextPtr;
};
typedef struct mychar Mychar;
void insert(Mychar **, char );
void printlist(Mychar **);
int main (void) {
Mychar *startPtr = NULL;
insert(&startPtr, 'b');
printlist(&startPtr);
}
void insert(Mychar **sPtr, char myvalue){
Mychar *newlinkPtr = calloc(1, sizeof(Mychar));
if (newlinkPtr == NULL)
{
fputs("Allocation failed!", stderr);
exit(1);
}
if (*sPtr == NULL){
newlinkPtr->value = myvalue;
newlinkPtr->nextPtr = *sPtr;
*sPtr = newlinkPtr;
}
}
void printlist(Mychar **startPtr){
printf("%cn", (*startPtr)->value);
}
输出:
b