提问人:DANAB 提问时间:2/4/2023 最后编辑:Vlad from MoscowDANAB 更新时间:2/5/2023 访问量:69
用于通过指针访问结构数组变量的每个元素的代码
A code for accessing each element of the structure array variable via pointer
问:
在以下行中:
struct student *ptr = NULL;
为什么 ptr 设置为 NULL??有人可以告诉我吗?
#include <stdio.h>
int main(void) {
// student structure
struct student {
char id[15];
char firstname[64];
char lastname[64];
float points;
};
// student structure variable
struct student std[3];
// student structure pointer variable
struct student *ptr = NULL;
// other variables
int i;
// assign std to ptr
ptr = std;
// get detail for user
for (i = 0; i < 3; i++) {
printf("Enter detail of student #%d\n", (i + 1));
printf("Enter ID: ");
scanf("%s", ptr->id);
printf("Enter first name: ");
scanf("%s", ptr->firstname);
printf("Enter last name: ");
scanf("%s", ptr->lastname);
printf("Enter Points: ");
scanf("%f", &ptr->points);
// update pointer to point at next element
// of the array std
ptr++;
}
// reset pointer back to the starting
// address of std array
ptr = std;
for (i = 0; i < 3; i++) {
printf("\nDetail of student #%d\n", (i + 1));
// display result via std variable
printf("\nResult via std\n");
printf("ID: %s\n", std[i].id);
printf("First Name: %s\n", std[i].firstname);
printf("Last Name: %s\n", std[i].lastname);
printf("Points: %f\n", std[i].points);
// display result via ptr variable
printf("\nResult via ptr\n");
printf("ID: %s\n", ptr->id);
printf("First Name: %s\n", ptr->firstname);
printf("Last Name: %s\n", ptr->lastname);
printf("Points: %f\n", ptr->points);
// update pointer to point at next element
// of the array std
ptr++;
}
return 0;
}
答:
指针的初始化方式NULL
// student structure pointer variable
struct student *ptr = NULL;
是多余的。
你可以通过结构数组的第一个元素在其声明中初始化它,比如
// student structure pointer variable
struct student *ptr = std;
代码的作者初始化了指针,因为他不想声明未初始化的指针,并且程序中的指针至少被重新分配了两次。NULL
因此,他似乎想将指针的声明和赋值与 .std
此外,由于指针仅在 for 循环中使用,因此最好在 for 循环语句中声明它,例如
for ( struct student *ptr = std; ptr != std + 3; ++ptr ) {
printf("Enter detail of student #%d\n", (i + 1));
printf("Enter ID: ");
scanf("%14s", ptr->id);
printf("Enter first name: ");
scanf("%63s", ptr->firstname);
printf("Enter last name: ");
scanf("%63s", ptr->lastname);
printf("Enter Points: ");
scanf("%f", &ptr->points);
}
应始终在使用变量的最小范围内声明变量。
请注意,它会更安全,而不是这些电话scanf
scanf("%s", ptr->id);
scanf("%s", ptr->firstname);
scanf("%s", ptr->lastname);
写
scanf("%14s", ptr->id);
scanf("%63s", ptr->firstname);
scanf("%63s", ptr->lastname);
还有一句话。与其使用幻数,不如引入一个命名常量,例如3
enum { N = 3 };
struct student std[N];
//...
for ( struct student *ptr = std; ptr != std + N; ++ptr ) {
在这种情况下,您的代码将更加灵活。只需更改常量的值就足够了,程序无需对程序进行任何其他更改即可运行。N
在发布的程序中,初始化是可选的。您可以删除它,该程序将完全相同。NULL
struct student *ptr = NULL;
int i;
ptr = std;
完全等价于
struct student *ptr;
int i;
ptr = std;
以及
struct student *ptr = std;
int i;
初始化变量的原因是鲁棒性,而不是正确性。健壮性是指在更改程序时将出现问题的风险降至最低。
假设您修改了程序,不小心删除了行。由于初始化为 ,当它在 for 循环中使用时,它将是一个空指针。如果您的程序崩溃或以其他方式出现异常,您可以在禁用优化的情况下编译它,并在调试器中运行它。然后,您会可靠地看到它在尝试取消引用 null 指针时崩溃,这清楚地表明该指针设置不正确。如果未初始化,则行为可能是任何内容,具体取决于当时内存中的内容,并且可能无法从一次执行复制到下一次执行,因此更难找到错误。ptr = std;
NULL
ptr
ptr
ptr
在此示例中,没有充分的理由选择初始化 to 而不是直接设置 。出于不同的原因,两者都可以被认为是良好的卫生习惯。初始化所有指向 null 的指针很好,因为它是一个简单的规则,它将无聊的初始化(您不需要太注意)与有趣的计算分开。另一方面,直接初始化到它需要的值是很好的,因为它最大限度地减少了发生的事情的数量。NULL
ptr = std
ptr
C 标准指出,具有自动存储持续时间的指针在声明时具有不确定的值,即它们未初始化,可能指向内存中的任何内容。
当指针的值不确定时使用指针是未定义的行为,因此在声明时(以及在调用 .NULL
free()
但 是必要的还是必需的?不。
如果要声明一个指针,并立即用一个值初始化它,那么将其设置为first是没有意义的。NULL
只在需要的地方声明也是一种很好的做法。 因此,而不是:
struct student *ptr = NULL;
// other variables
int i;
// assign std to ptr
ptr = std;
你可以这样写:
int i;
struct student *ptr = NULL;
另一个好的做法是避免用不必要的注释使代码混乱。
// assign std to ptr
ptr = std;
上面的评论没有任何用处,很明显被分配给了.std
ptr
评论
NULL