与时俱进学习C语言

本文选自:https://mp.weixin.qq.com/s/D_NjVesiFtz5_TTjH9myxQ 

https://mp.weixin.qq.com/s/WdYJN4Xc4ns4xhY-lBxhzQ

1983年,美国国家标准协会(American National StandardsInstitute)开始对C语言进行标准化,并于1989年推出C语言和C标准库的标准。该标准通常被称为ANSIC。由于该标准是1989年推出的,因此也被称为C89。时隔一年,1990国际标准协会ISO参照ANSI标准,推出一模一样的C语言和C标准库标准,将其作为ISO/IEC9899:1990国际标准,由于该标准是1990年提出的,因此被称为C90标准。可见C89、C90和ANSI C是指同一个标准。

1994年,ANSI/ISO联合组织想要为ANSIC标准加入有限的改动,使C标准在国际化字符、一些明显的缺陷、数值计算上更上一层楼,推出了C99标准。2011年12月8日,ISO发布了ISO/IEC9899:2011C语言标准,俗称C11。2018年6月,ISO发布了ISO/IEC9899:2018标准,这个标准通常称为C18(有时也称C17),它是C11的bug修复版,没有任何新的特性。C18是C语言的现行标准,未来将有新的标准C2X推出。

C语言主要有两大类标准,由三个组织制定,这三个组织分别是:

自由软件基金会(Free Software Foundation,FSF):是一个致力于推广自由软件、促进计算机用户自由的美国民间非盈利性组织。它于1985年10月由理查德·斯托曼建立。其主要工作是执行GNU计划,开发更多的自由软件,完善自由软件理念。Linux和GNU就是由这个组织维护的。

美国国家标准学会(American NationalStandards Institute,ANSI):它是非赢利性质的民间标准化团体,但它实际上已成为美国国家标准化中心,美国各界标准化活动都围绕它进行。

国际标准化组织(International Organizationfor Standardization,ISO)是标准化领域中的一个国际性非政府组织,致力于制定国际标准。

美国国家标准学会制定的C语言标准简称为ANSI C,国际标准化组织制定的C语言标准简称为标准CISO C。大约在90年代,ANSI与ISO相互接纳吸收对方的标准,所以,当前的标准C与ANSI C标准是一样的。GNU C 是自由软件基金会制定的C语言标准,它主要应用于Linux开发,比标准C支持更多的特性,所以GNU C≠标准C=ANSI C。

由于GNU C比标准C支持更多的特性,所以使用起来更加灵活,下面举例说明。

GNU C允许定义长度为0的数组,可能很多人会问长度为0的数组有什么用呢?当我们定义一个长度为0的数组时,说明这个数组不占用内存空间,但是我们可以通过这个数组来访问数组后面的变量,比如下面这个结构体:

struct data_pra {
  char name[20]; //姓名 
  int start[0]; 
  int num;    //学号 
  int math;      //数学成绩 
  int chinese;   //语文成绩   
};
struct data_pra student[10];

我们可以看到结构体中的start[0]、num、math和chinese都有相同类型,可以通过student[0].start[0]访问num变量,student[0].start[1]访问math变量,student[0].start[2]访问chinese变量等等。这样处理,可以使用循环语句实现数据的输入,简化了程序。参看以下程序。

#include <stdio.h>
struct data_pra {    
  char name[20]; //姓名
  int start[0]; 
  int num;    //学号 
  int math;      //数学成绩 
  int chinese;   //语文成绩   
};
int main() {
  struct data_pra student[10];
  int i,j;
  for (i=0;i<2;i++) {
    printf("请输入姓名:");
    scanf("%s",student[i].name);
    printf("请依次输入学号 语文成绩 数学成绩: ");
    for(j=0;j<3;j++) {
      scanf("%d",&student[i].start[j]);      
    }    
  }
  printf("\n");
  for(i=0;i<2;i++) {
    printf("姓名:%s ",student[i].name);
    printf("学号:%d\t",student[i].num);
    printf("数学成绩:%d\t",student[i].math);
    printf("语文成绩:%d\n",student[i].chinese);    
  } 
  return 0;
}

程序运行结果如下图所示。

图片

注:本博主使用Dev C++开发环境。它支持C90/C99/GNU C90/GNU C99

虽然C语言新标准不断推出,但是,国内大多数C程序设计教材还停留在C90,包括国内最著名的教材,该教材的第五版仍然讲的是C90。虽然该教材在前言中说本教材是按照C99标准进行介绍的,但在内容介绍上仍然保留C90的内容。

由于教材无法跟上时代的步伐,学生获得的C语言知识没有得到更新,使得教学严重脱离应用。举一个例子:请看下面这个程序是否有错?


#include <stdio.h>
int fsize3(int n) {  
  char b[n+3];
  return sizeof b;
}
int main() {
  int n;
  n=4;
  printf("\t%d\n",fsize3(n));
  n=7;
  printf("\t%d\n",fsize3(n));
  return 0;
}

大多数同学回答该程序的第3行有错误,因为,定义数组的下标表达式中有变量,他们接受的知识是数组下标必须是常量表达式!上面所说的那本著名教材在讲这个知识点时就是这么描述的,且专门举例说明“int a[3+5];"是合法的,”int a[n];"是不合法的。

那好,我们看编译器是否能正确编译上面这个程序?

编译结果如下图所示,该程序被正确编译了。

图片

程序运行结果如下。

图片

看到这个结果是否颠覆了你的认知?

从C99标准开始C语言支持VLA(Variable-length array,变长数组),VLA有如下特点:

1. 其长度不是编译时计算,而是运行时计算,因此长度可以用任意整型表达式指定。如上例程序中,第一次调用时,b有7个元素,第二次调用时,b有10个元素。

2. 没有初始化式,比如我们可以对数组a进行初始化,

int a[5]={1,2,3,4,5};

但不能对上例中的b进行初始化,因为b的下标表达式中有变量,在未使用前,无法确定下标个数。

3. 一般用在main()之

外的其他函数中,每次调用长度可以不同,如上例。

但在使用变长数组时一定要注意,下标中的变量在定义数组之前一定要赋值,否则,程序运行时有可能出错,因为,变量没有赋初值,其值是一个随机数,这个数可能很大,在定义数组时,由于申请的内存过大而导致内存出错。可参看下面2个截图,第一个截图,程序正确退出,第二个截图,程序异常退出。当然,如果下标中的变量已经赋值,但下标表达式计算结果过大,仍然会造成内存异常的。

图片

 

图片

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lhw---9999

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值