用于通过指针访问结构数组变量的每个元素的代码

A code for accessing each element of the structure array variable via pointer

提问人:DANAB 提问时间:2/4/2023 最后编辑:Vlad from MoscowDANAB 更新时间:2/5/2023 访问量:69

问:

在以下行中:

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;
}
C 指针 null 初始化 声明

评论

0赞 Beta 2/4/2023
将该变量设置为 不起作用,因为它会在几行后被赋予另一个值。这可能只是习惯性的整洁。NULL

答:

0赞 Vlad from Moscow 2/4/2023 #1

指针的初始化方式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

0赞 Gilles 'SO- stop being evil' 2/5/2023 #2

在发布的程序中,初始化是可选的。您可以删除它,该程序将完全相同。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;NULLptrptrptr

在此示例中,没有充分的理由选择初始化 to 而不是直接设置 。出于不同的原因,两者都可以被认为是良好的卫生习惯。初始化所有指向 null 的指针很好,因为它是一个简单的规则,它将无聊的初始化(您不需要太注意)与有趣的计算分开。另一方面,直接初始化到它需要的值是很好的,因为它最大限度地减少了发生的事情的数量。NULLptr = stdptr

0赞 Harith 2/5/2023 #3

C 标准指出,具有自动存储持续时间的指针在声明时具有不确定的值,即它们未初始化,可能指向内存中的任何内容。

当指针的值不确定时使用指针是未定义的行为,因此在声明时(以及在调用 .NULLfree()

但 是必要的还是必需的?不。

如果要声明一个指针,并立即用一个值初始化它,那么将其设置为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;

上面的评论没有任何用处,很明显被分配给了.stdptr