You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言结构体数组填充逻辑移至main函数的实现及scanf的&使用规则

程序运行异常的修复方案

当前代码存在的具体问题

  • 循环变量i未在main函数作用域内声明,编译阶段就会直接报错,属于基础语法错误
  • 循环内传入函数的地址没有做对应偏移:三次循环都把数组首地址std传给getDetail,不管循环执行多少次,永远只会给数组的第一个元素赋值,剩下两个学生的存储空间从来没有被写入
  • getDetail函数内部的ptr++是无效操作:C语言的函数参数是值传递,函数内对形参ptr做的自增修改,只会影响函数内部的局部变量副本,完全不会影响外面传入的实参,在你当前的设计下这段代码属于旧逻辑遗留,没有任何作用
  • 最初参考的示例代码末尾多写了一个闭合大括号},存在语法错误

调整后的可正常运行的代码

#include <stdio.h>    
// 学生结构体定义
struct student {
  char id[15];
  char firstname[64];
  char lastname[64];
  float points;
};

// 函数声明
void getDetail(struct student *);

int main(void) {
  // 存储3个学生信息的结构体数组
  struct student std[3];
  int i; // 显式定义循环变量i

  for (i = 0; i < 3; i++) { 
    printf("Enter detail of student #%d\n", (i + 1));
    // 传入当前遍历位置的学生结构体地址,等价于 std + i
    getDetail(&std[i]);
  }
  
  return 0;
}

// 函数定义:仅负责给传入的单个结构体填充用户输入的信息
void getDetail(struct student *ptr) {
    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);
}

scanf参数中&的使用规则

scanf的核心要求是:必须拿到目标存储位置的内存地址,才能把用户输入的值写入到对应的内存空间,要不要加&,完全看你传入的表达式本身是不是已经代表了内存地址。

  • 读取数组成员(比如id、firstname、lastname)时不需要加&:
    C语言中,数组名作为普通表达式使用时,会自动隐式转换为指向数组首元素的指针,本质就是一个地址值。比如ptr->id本身就等价于&ptr->id[0],已经满足scanf对参数的地址要求,不需要额外加取地址符。
  • 读取非数组的标量成员(比如points)时必须加&:
    points是普通的浮点类型变量,直接写ptr->points拿到的是这个变量存储的浮点数值,而不是它的内存地址。scanf无法通过值定位到要写入的内存位置,必须加上&取地址,把points的内存位置传给scanf,才能正确完成输入写入。

注意:不要混淆数组首元素地址和整个数组地址的区别。虽然ptr->id(首元素地址)和&ptr->id(整个数组的地址)的数值是完全一样的,但二者类型不同,直接写数组名是和scanf的字符串读取要求完全匹配的正确写法。


内容的提问来源于stack exchange,提问作者pingu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.23 12:15:03