文章目录
基本类型
1. 我该如何决定使用哪种数据类型?
- 如果可能用到很大的数值(大于32767或者小于-32767),就使用
long
类型.否则,如果空间很重要(例如有很大的数组或者很多的结构),就使用short
类型.其他的情况就用int
类型.- 尽管字符类型(尤其是无符号的 unsigned char类型)可以当成小整数使用,但是尽量不要这么用.编译器需要生成额外的代码来进行char和int类型之间的转换.
- 决定使用float类型还是double类型的时候,也要有类似的空间/时间权衡.(很多编译器在表达式求值的时候仍然把所有的float类型转换为double类型进行运算).但是如果一个变量的地址确定切必须为特定的类型的时候,就不会再进行强制的转换.
2.C语言类型大小没有精确的定义,只能确保如下几点
char
类型可以存放小于等于127的值short int
和int
可以存放小于等于32767的值long int
可以存放小于等于2147483647的值char
至少有8位,short int
和int
至少有16位,而long int
至少有32位,long long
至少有64位
指针声明
1. 指针声明有什么问题?
char *p1,p2;
声明的本身没有问题,但是p2不是一个指针.指针声明中的*号不是基本类型的一部分,它只是包含被声明标识符的声明符的一部分.声明的语法和解释并非
类型 标识符
而是
基本类型 生成基本类型的东西
其中生成基本类型的东西-声明符-或者是一个简单的标识符,例如*p a[10] f()这样的符号,表明被声明的变量是指向基本类型的指针,基本类型的数组或者返回基本类型的含糊.
所以以上的声明,基本的类型都是char,只是第一个是指针,第二个是基本类型char,而非指针.
正确的声明是这样的
char *p1, *p2
2. 声明指针,并且分配空间
char *p;
*p = malloc(10);
注意声明的指针是p
而不是*p
3. 怎么样声明和定义全局变量和函数最好?
- 尽管一个全局变量或者函数可以(在多个编译单元中)有多处
声明
,但是定义
却最多允许出现一次.对于全局变量,定义是真正分配空间并赋初始的声明.对于函数,定义是提供函数体的声明
.- 这些是声明
extern int i
,extern int f()
, 这些是定义:int i = 0 int f() { return 1;}
- 函数的声明中,extern是可选的.
- 当希望多个源文件中共享变量或者函数的时候,需要确保定义和声明的一致性.最好的安排是在某个相关的
.c
文件中定义,然后在头文件.h
中进行外部声明,在需要的时候,只要包含对应的头文件即可.定义变量的.c
文件也应该包含该头文件- 永远不要把外部函数的原型放到
.c
文件中.如果函数的定义发生了改变,很容易忘记修改原型,而错误的原型贻害无穷
存储类型和类型定义
1. extern在函数的声明中是什么意思?
存储类型
extern
只对数据声明有意义.对于函数声明,它可以用作一种格式上的提示,表示这个函数的定义可能在另一个源文件中.本质上并没有任何的区别
2. typedef 和 #define有什么区别?
一般来说,最好使用
typedef
,它能正确的处理指针类型.
#include <stdio.h>
typedef char *String_t;
#define String_d char *
int main()
{
String_t s1,s2; // 这里的s1 和 s2都是指针类型. 因为String_t代表的是一种char*类型
String_d s3,s4; // 这里的String_d 只是字符串的替换,等价于 char * s3,s4. s3是char*类型,
//而s4是char类型
return 0;
}
主要区别如下
- 原理不同
#define
是C语言中的定义的语法,是预处理指令,在预处理进行简单的机械的字符串的替换,不作正确性检查.typedef
是关键字,在编译时处理,有类型检查的功能.它在自己的作用域内给一个已经存在的类型的一个别名,但不能再一个函数定义里面使用typedef.- 功能不同
typedef
是用来定义类型的别名,祈祷类型易于记忆的功能.另一个功能是定义机器无关的类型.如定义一个REAL
的浮点类型,在目标机器上它可以获得最高的精度 typedef long double REAL.在不支持long double的机器上,看起来是这样的,typedef double REAL,在不支持double的机器上,是这样的 typedef float REAL #define 不只是可以为类型取别名,还可以定义常量,变量,编译开关等- 作用域不同 #define么有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用,而typedef有自己的作用域
结构体的定义
1. 什么是结构体
- 结构体是多种类型的数据的集合
- 结构体是一种由用户自定义的特殊的复合型的
数据类型
- 结构体就像一个模板,结构体存放的东西在内存上整体上是连续的,但是因为有对齐的需要,所以实际上成员变量之间存在
裂缝
.
2. 结构体的声明
#include <stdio.h>
struct stu
{
char *name; // 姓名
int num; // 学号
int age; // 年龄
char group; // 所在
float score;
};
int main()
{
stu s1,s2;
return 0;
}
3. 定义链表的时候,结构体指向自己的问题
typedef struct {
char *item;
NODEPTR next;
} * NODEPRT;
在C语言中的结构当然可以包含指向自己的指针.
这里的问题是typedef,typedef定义了一个新的类型名称.但是不能再定义typedef类型以前使用它.
在上面的代码中,在next域声明的地方还没有定义NODEPTR.
要解决这个问题,首先赋予这个结构一个标签(‘struct node’),然后声明next域为struct node *,或者分开typedef声明和结构定义.
修正后版本
typedef struct node{
char *item;
struct node *next;
} *NODEPTR;
也可以在声明结构之前先用typedef,然后就可以在声明next域的时候使用类型定义NODEPTR了
struct node;
typedef struct node *NODEPTR;
struct node {
char *item;
NODEPTR next;
};
两种风格都使用的版本
struct node{
char *item;
struct node *next;
};
typedef struct node *NODEPTR;