user-0 提问: 初学C，想请教一下有关结构体的问题。

回复:
user: user-1
content: 第一个问题：函数声明，建议在函数体外，最好在文件的前端，头文件以下的地方。 第二个问题：分数和平均分建议使用float类型，因为对于你的数据float的精度和取值范围足够你的使用，double是高精度的，其实也用不了那么大的精度，反而占用更多的内存空间。 第三个问题：输入一次，第二次就直接退出了。原因是输入缓存里有垃圾数据，而getchar()又得到了这些垃圾数据，所以进入default了，这些垃圾数据就是上次输入残留下来的，比如回车符等其他数据。建议使用int类型的1，2，3，4来区分每个功能。 第四个问题：出现乱码一般就是没有找到字符串结束符，在你的程序里也有可能是字符串赋值越界导致。 以下是修改后的程序： 第五个问题：p+i与p++都是做偏移，一个是通过offset便宜量来完成，但本身值不变，p++也是偏移，但其偏移是修改自己的地址值完成的。还有有区别的，区别之处就是对p本身有没有修改。 #include<stdio.h>  #define LEN 20 #define NUM 3 #define CSIZE 4   struct name{     char lname[LEN];     char fname[LEN]; }; struct student{     struct name fun;     float grade[NUM];     float aver; };  void get_score(struct student *p); void calculate_average(struct student *p); void print_each(struct student *p);  void get_score(struct student *p) {     int i, j = 0;     for (i = 0; i < CSIZE;i++)     {         printf("input the %d score of %s %s\n", i + 1, p->fun.fname, p->fun.lname);         for (j = 0; j < NUM; j++)             scanf("%f", &p->grade[j]);         p++;     } } void calculate_average(struct student *p) {     int i, j;     float total = 0;      for (i = 0; i < CSIZE; i++)     {         for (j = 0; j < NUM; j++)         {             total += p->grade[j];         }         p->aver = total/NUM;         total = 0.0; /* note， 每个人的total不一样。 */         p++;     } } void print_each(struct student *p) {     int i, j;      for (i = 0; i < CSIZE; i++)     {         printf("%s %s\t", p->fun.fname, p->fun.lname);         for (j = 0; j < NUM; j++)             printf("%.2f\t", p->grade[j]);         printf("%.2f\n", p->aver);         p++;     } } int main(void) {     int ch;     struct student stu[CSIZE] = {         { "kaihang", "chen" },         { "kaichuan", "chen" },         { "kaixiang", "chen" },         { "youpu", "chen" }     };     while (1)     {         printf("Please input your choice:\n(1: add grade, 2: cal aver, 3: show info, 4: exit): ");         scanf("%d", &ch);          switch (ch)         {             case 1:                 get_score(stu); break;             case 2:                 calculate_average(stu); break;             case 3:                 print_each(stu); break;             default:                 puts("Bye!"); return 0;         }     }     return 0; }

user: user-2
content: void get_score(struct student *p) {     int i, j = 0;     for (i = 0; i < CSIZE; i++)     {         printf("input the %d score of %s %s\n", i + 1, p->fun.fname, p->fun.lname);         for (j = 0; j < NUM; j++)             scanf("%lf", &p->grade[j]); //scanf 输入double数据必须使用lf，不能用f替代         p++;     } }  int main() {     void get_score(struct student *p);     void calculate_average(struct student *p);     void print_each(struct student *p);     struct student *p;     struct student stu[CSIZE] = {         { "kaihang", "chen" },         { "kaichuan", "chen" },         { "kaixiang", "chen" },         { "youpu", "chen" }     };     while (1)     {         char ch = getchar();         if (ch == '\n')             continue;          switch (ch)         {         case 'd':get_score(stu); break;         case 'e':calculate_average(stu); break;         case 'f':print_each(stu); break;         default:puts("Bye!"); return 0;         }     }     return 0; }  指出两个不妥的地方

user: user-3
content: p++会改变原来p指针的指向，而(p+i)->是不会的  Debug模式下C程序，发现栈区开辟的存储空间都是使用0CCCCCCCCh来填充4字节单位的，也就是说，栈区开辟的存取局部变量的空间的每一个字节都被0xCC填充了。（为什么用0xCC，这个是int 3h的机器码，下断点用的）两个0xCC合起来输出时恰好对应中文“烫”字。动态分配的空间开辟的堆，VC的Debug用0xCD填充堆的空间，两个0xCD和在一起就是屯了。  单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

user: user-4
content: 参考 http://blog.csdn.net/yes_i_am/article/details/52003511