C数据类型

 

C数据类型

学习一门编程语言时,要注意:

1. 这门语言提供了哪些Primitive,比如基本数据类型,比如基本的运算符、表达式和语句。

2. 这门语言提供了哪些组合规则,比如复合数据类型,比如表达式和语句的组合规则。

3. 这门语言提供了哪些抽象机制,例如数据抽象和过程抽象(Procedure Abstraction)。

最简单的过程抽象:把一组语句用函数名封装起来

 

  • 复合数据类型——结构体(定义结构体类型,定义结构体类型的变量)

struct complex_struct{

       double x,y;

};

定义了complex_struct这个标识符,命名规则就和变量一样,但它不表示一个变量,而表示一个类型,这种标识符在C语言中称为Tag,struct complex_struct {double x, y; }整个可以看作一个类型名,就像int或double一样,只不过它是一个复合类型。定义在函数外面,就像全局变量一样,这样定义的Tag在其定义之后的各函数中都可使用。

定义结构体变量:有两个成员x和y,使用.运算符访问,存储空间相邻。

struct complex_struct{

       double x,y;

}z1,z2;

Struct complex_struct z3,z4;

在定义结构体类型的同时定义了变量,可不写Tag,但没有办法再次引用这个结构体类型了。

Struct{

       double x,y;

}z1,z2;

初始化:struct complex_struct z = { 3.0, 4.0 };  赋值不可以用这种语法

如果Initializer中的数据比结构体的成员多,编译器会报错,但如果只是末尾多个逗号不算错。如果Initializer中的数据比结构体的成员少,未指定的成员将用0来初始化,就像未初始化的全局变量一样。

+-*/等算术运算符和&&、||、!等逻辑运算符都不能作用于结构体类型,if、while的控制表达式的值也不能是结构体类型。严格来说,可以做算术运算的类型称为算术类型(ArithmeticType),算术类型包括整型和浮点型。可以做逻辑与、或、非运算的操作数或者if、for、while的控制表达式的类型称为标量类型(Scalar Type),标量类型包括算术类型和指针类型。

结构体类型之间可以用赋值运算符,可以用一个结构体初始化另一个结构体,可当做函数的参数和返回值来传递。

  • 枚举类型

enum coordinate_type {REC,FOLAT};

枚举类型的成员是常量,它们的值编译器自动分配,例如定义了上面的枚举类型之后,REC就表示常量0,POLAR就表示常量1.

  • 复合类型——数组Array

由一系列相同类型的元素组成,存储空间相邻

int count[4]; //定义一个由4个整数组成的数组count

初始化int count[4]={4,3,2,1};

C编译器并不检查count[-1]或是count[100]这样的访问越界错误,编译时能顺利通过,所以属于运行时错误。

VS结构体,数组不能互相赋值,不能作为函数的参数或返回值。原因:数组名做右值使用时,自动转换成指向数组首元素的指针。函数调用使用数组名时,其实是传一个指针类型的参数,而不是数组类型的参数。

a = b这个表达式,a和b都是数组类型的变量,但是b做右值使用,自动转换成指针类型,而左边仍是数组类型,所以编译器报的错误信息是error: incompatible types in assignment。

  • 字符串

看做 一个数组,元素是字符型的。做右值使用时自动转换成指向首元素的指针。

 

写程序时对用户输入要格外小心,用户有可能输入任何数据。

scanf("%d", &man)这个调用的功能是等待用户输入一个整数并回车,这个整数会被scanf函数保存在man这个整型变量里。如果用户输入合法(输入的确实是整数而不是字符串),则scanf函数返回1,表示成功读入一个数据。

在传给scanf的第一个参数中用%d、%f或%c表示读入一个整数、浮点数或字符,则第二个参数的形式应该是&运算符加一个相应类型的变量名,表示读进来的数存到这个变量中;如果在第一个参数中用%s读入一个字符串,则第二个参数应该是数组名,数组名前面不加&,因为数组类型做右值时自动转换成指针类型,而scanf后面这个参数要的就是指针类型。

scanf("%s",input)等待用户输入一个字符串并回车,,scanf把其中第一段非空白(非空格、Tab、换行)的字符串放到input数组中,并自动在末尾添加'\0'。