C语言基础

C是什么样的语言

  • 为了解决眼前问题由开发现场的人发明的
  • 虽然使用方便,但看上去不怎么顺眼。
  • 不熟悉的人糊里糊涂地使用,难免会带来悲剧的语言。

C语言发展历程

C语言原来是为了开发UNIX操作系统而设计的语言,最早的UNIX是用汇编来写的。UNIX开发者Ken Tompson因为厌倦苦哈哈地使用汇编,开发了一种称为B的语言。B语言是1967年剑桥大学的Martin Richard开发的BCPL(Basic CPL)的精简版本。BCPL的前身是1963年剑桥大学和伦敦大学共同研究开发的CPL(Combined Programming Language)语言。

B语言不直接生成机器码,由编译器生成栈式机(Stack Machine)用的中间代码,中间代码通过解释器(Interpreter)执行,类似Java和早期的Pascal。因此,B语言的执行效率非常低。结果在后来的UNIX开发过程中人们放弃了使用B语言。

1971年,Ken Tompson的同事Dennis Ritchie对B语言做了改良,追加了char数据类型,并让B语言可以直接生成PDP-11的机器代码。曾经在很短时间内,大家将这门语言称为NB(New B),之后NB改称为C语言。后来,为了满足使用UNIX的程序员的需要,C语言一边接受来自各方面的建议,一边摸着石头过河般地进行着周而复始的功能扩展。

  • PDP-11 原DEC(美国数字设备公司)生成的微型电脑

B是什么样的语言

B语言是在虚拟机上运行的、解释性的开发语言。B语言没有像Java那样想要去实现“到处运行”的宏伟目标,只是因为当时运行UNIX的PDP-7硬件环境的限制,只能采用解释器这样的实现方式。

B是没有类型的语言,虽然C语言中有char、short、int、float、double等数据类型,但B使用的数据类型只有word,可以认为和int差不多。对于指针,在B语言里面和整数一样使用。因为无论怎么说,指针无非就是内存中的地址。对于机器来说,指针是可以和整形同样对待的。

C语言的理念

ANSI C标准中附有理论依据(Rationale),理论依据中有“keep the sprit of C”。

keep the sprit of C
- Trust the programmer
- Don't prevent the programmer from doing what needs to be done
- Keep the language small and simple
- Provide only way to do an operation
- Make it fast, event if it is not guaranteed to be portable.
保持C的精神
- 请信任程序员
- 不要阻止程序员去做需要做的工作
- 保持语言的小巧和简单
- 为每种操作只提供一种方法
- 就算不能保证可移植性,也要追求运行效率。

C语言是抱着“程序员万能”的理念设计出来的。在C语言的设计中,有效考虑的是:

  • 如何才能简单地实现编译器
  • 如何才能让程序员写出能够生成高效执行代码的程序

C是只能使用标量的语言

对于标量(Scale)简单来说就是指char、int、double、enum等数值类型,以及指针。相对的像数组、结构体、联合体这样的将多个标量进行组合的类型称为聚合类型(Aggregate)。

$ vim test.c
#include 
#include 

int main()
{
  int char[] = "ok";
  if(char=="ok"){
    printf("success\n");
  }else{
    printf("fail\n");
  }
  return 0;
}
$ gcc test.c -o test
$ test.exe
fail

原因解析:

  • 表达式不是在比较字符串的内容,只是在比较指针。
  • 字符串本质是char类型的数组,也就是说字符串不是标量,在C语言当然不能使用==进行比较。

恶名昭著的指针究竟是什么

指针是一种保存变量地址的变量,在C中频繁地使用。

在C语言标准中最初出现指针的部分是这么说的:

指针类型(pointer type)可由函数类型、对象类型或不完全的类型派生,派生指针类型的类型称为引用类型。指针类型描述一个对象,该类对象的值提供对该引用实体的引用。由引用类型T派生的指针类型有时称为“(指向)T的指针”。从引用类型构造指针类型的过程称为“指针类型的派生”。这些构造派生类型的方法可以递归地应用。

指针类型其实不是单独存在的,是由其他类型派生而来的。由引用类型T派生的指针类型有时称为“(指向)T的指针”,也就是说,实际上存在的类型是“指向int的指针类型”、“指向double的指针类型”。

因为指针类型是类型,所以和int类型、double类型一样,也存在“指针类型变量”和“指针类型的值”。糟糕的是,“指针类型”、“指针类型变量”、“指针类型的值”经常简单粗暴的统称为“指针”。注意先有“指针类型”,因为有了“指针类型”,所有有了“指针类型的变量”和“指针类型的值”。指针类型的值实际是指向内存的地址。

$ vim pointer.c
#include 

int main()
{
  int hoge=1;
  int piyo=2;
  int *pointer;
  printf("&hoge=%p\n&piyo=%p\n&pointer=%p\n", &hoge, &piyo, &pointer);

  pointer = &hoge;
  printf("pointer=%p\n*pointer=%d\n", pointer, pointer);

 *pointer = 100;
  printf("hoge = %d\n", hoge);

  return 0;
}
$ gcc pointer.c -o pointer
$ pointer.exe
&hoge=0028FF3C
&piyo=0028FF38
&pointer=0028FF34
pointer=0028FF3C
*pointer=2686780
hoge=100
C语言基础_第1张图片
变量在内存中的保存状况

注意:变量不一定按照声明的顺序保存在内存中

因为存在指针类型,所以存在指针类型的变量和指针类型的值。使用%p输出的地址指的就是指针类型的值。对变量实施&运算获取变量的地址,也称为指向变量的指针(指针类型的值)。

page32

你可能感兴趣的:(C语言基础)