C基础

1-结构话程序设计:自顶向下,逐步细化,模块化设计,结构化编码
2-C语言程序设计以函数为单位
3-数据类型,指定数据取值范围及对该数据可进行的操作
4-<编辑器(*.c, *.cpp)--预处理--编译器(*.obj)--连接器(*.exe)>(磁盘)--载入器--内存--CPU
5-标识符,大小写字母/下划线开头, 字母下划线,数字组合
6-数据类型-基本数据类型(enum)、指针数据类型,构造数据类型(struct,union)
7-整型 八、十、十六进制。  short类型两个字节,-32768~32767
_int8 = char
_int16 = short
_int32 = int = long
_int64 = long long
int i = 017;  // 八
int j = 15;
int k = 0x0f; // 十六
// 三个值相等都是15
unsigned short twobyte; // 0 - 65535
unsigned fourbyte;  
unsigned long fourbyte;  // 因系统而变,long unsigned也可以,关键字顺序可以改变
8-科学计数法, E|e在中间  左边小数/整数(.77),    右边整数(正负0)
9-小数 double/float 常量系统默认为double,  float k = .33; 警告,.33为double类型
10-空void,这种指针可以指向任意类型
11-字符型char,  'a',   转义字符'\n'..., 不支持中文
12-字符串类型,支持中文。
13-常量  字面常量,标识常量(只读,且必须声明即初始化)
const int MIN = 0;  // int const 也一样
14-引用:变量和对象别名(必须声明即初始化)
int x = 8;
int &t = x;   // x,t共同对应一个内存,都可以修改内存中的数值
const int &f = x;  // 常引用,只能读取8,不能修改8
&f // 脱离int,&不是引用意思,而是取地址了
15-运算符-初等运算符--单目--算术--左右移--关系--位运算符
++在前,是+,后使用
/ (支持浮点型)
% (只支持整数,余数符号由被除数决定),位运算只支持整数
<< 右边补0     >> 无符号数,补0 ,有符号,符号位是1,补1,符号0,补0

优先级

运算符

名称或含义

使用形式

结合方向

说明

1初等运算符,除了()都是关于寻址的

[]

数组下标

数组名[常量表达式]

左到右

 

()

圆括号

(表达式)/函数名(形参表)

 

.

成员选择(对象)

对象.成员名

 

->

成员选择(指针)

对象指针->成员名

 

2单目运算符

-

负号运算符

-表达式

右到左

单目运算符

(类型)

强制类型转换

(数据类型)表达式

 

++

自增运算符

++变量名/变量名++

单目运算符

--

自减运算符

--变量名/变量名--

单目运算符

*

取值运算符

*指针变量

单目运算符

&

取地址运算符

&变量名

单目运算符

!

逻辑非运算符

!表达式

单目运算符

~

按位取反运算符

~表达式

单目运算符

sizeof

长度运算符

sizeof(表达式)

 

3算术运算符

/

表达式/表达式

左到右

双目运算符

*

表达式*表达式

双目运算符

%

余数(取模)

整型表达式/整型表达式

双目运算符

4

+

表达式+表达式

左到右

双目运算符

-

表达式-表达式

双目运算符

5

<<

左移

变量<<表达式

左到右

双目运算符

>>

右移

变量>>表达式

双目运算符

6关系运算符

>

大于

表达式>表达式

左到右

双目运算符

>=

大于等于

表达式>=表达式

双目运算符

<

小于

表达式<表达式

双目运算符

<=

小于等于

表达式<=表达式

双目运算符

7

==

等于

表达式==表达式

左到右

双目运算符

!=

不等于

表达式!= 表达式

双目运算符

8位运算符

&

按位与

表达式&表达式

左到右

双目运算符

9

^

按位异或

表达式^表达式

左到右

双目运算符

10

|

按位或

表达式|表达式

左到右

双目运算符

11

&&

逻辑与

表达式&&表达式

左到右

双目运算符

12

||

逻辑或

表达式||表达式

左到右

双目运算符

13

?:

条件运算符

表达式1? 表达式2: 表达式3

右到左

三目运算符

14赋值预算符

=

赋值运算符

变量=表达式

右到左

 

/=

除后赋值

变量/=表达式

 

*=

乘后赋值

变量*=表达式

 

%=

取模后赋值

变量%=表达式

 

+=

加后赋值

变量+=表达式

 

-=

减后赋值

变量-=表达式

 

<<=

左移后赋值

变量<<=表达式

 

>>=

右移后赋值

变量>>=表达式

 

&=

按位与后赋值

变量&=表达式

 

^=

按位异或后赋值

变量^=表达式

 

|=

按位或后赋值

变量|=表达式

 

15

,

逗号运算符

表达式,表达式,…

左到右

从左向右顺序运算

16-类型转换 隐式类型转换,低类型数据转换高类型, 强制转换(int)a; int (a);
17-goto, 
loop: cin >> number;
        number = - number;
        goto loop;
18-break;跳出整个循环,continue重新开始循环,for(;;)永真。
19-exp1?exp2:exp3;   exp1真执行exp2,假执行exp3;
20-do, while for
21-switch, case语句没有break,会往下继续执行。这次不用判断是否符合。仅支持字符,整型,枚举
switch(x)
{
case 1:       // 1执行后,继续2,因为没有break;
case 2:       break;    // 执行后不会,有break;
default:           // java还是会有。不需要break;  
}
22-数组-具有一定顺序关系的若干相同类型变量集合体,内存连续,多维也是。
22.1数组名,数组存储空间的开始地址,*a,可以取到第一个值,&a==a,  不可改变,a++会报错,之后将其付给指针,用指针才能加加。,sizeof(a)得到数组的大小,而不紧紧是指针的大小,int *p, sizeof(p)为4
22.2数组没有初始化的,默认为0
22.3字符数组末尾一定要为‘/0’。不然系统会默认为‘/0’;如果刻意这样 char a[2] = {'a','c'};就不是字符串数组了。
// 特殊表示法
int a[5] ={1,5,5,6,4}; int i = 4
a[4] = 4[a] = i[a];
// 一维数组
    int a[] = {2,3};  // 可以不是先说明数组元素个数,但是一定要先初始化,a[2]可以不用。不说个数一定要先初始化。
    cout << *a << endl;

    // 二维数组
    int b[][4] = {4,{3}};  // b是二维指针不能赋值给一维指针
    int c[3][4] = {13};  // c[0]类似上面的a,是一个指针。c是一个二维指针,指向三个指针,指针又指向数组
23-指针,四个字节,变量或常量的地址
23.1两个指针,一个new出的,一个非new的,一个指向堆,一个指向栈,或者没有指向
delete的工作就是让刷新p指向的内容,标记该块内存可用。p的指向没有改变。但这个指向随时有被系统回收的危险
一个指向栈的指针,让他指向堆之后,他就和new的没有差别了,同样可以delete
int a[5] = {1,2,3,4,5};
sizeof(a); // 20  指针作为参数,会丢失size,这是数组和指针一模一样
int func(int *a)
{
sizeof(a); // 4;
//定义数组a[5];sizeof(a)为20;将a赋给指针p。sizeof(p)还是为4;即使是p = new int[5];还是4。 那是因为sizeof 操作符不能返回动态地被分派了的数组或外部的数组的尺寸
// 数组是静态的。数组是存在栈里的,不能什么太大的,少用好。
//数组的首地址就是sizeof得到的是整个数组的大小,而其他指针都是4,即使是由数组首地址或者malloc,new分到的数组都是4
// 1-sizeof求系统分配的内存,而strlen求个数,仅适用于char *

}
23.2,常指针比普通指针多了个可以指向常量的功能,指针常量则,现在指针不能改变指向,两个综合也就都具备而已

类型

 

指针变量

Int *p;

指向常量的指针

Const int *p;

指针常量

Int *Const p;

指向常量的指针常量

Const int *const p;

是否可以指向变量

(指针是常量,一指向无法修改)

是否可以指向常量

(p指针无法通过const 指针赋值)

(和左边第二格一样)

(由于多了个const)

是否可以重新指向

是否可以改变指向的内存单元的值

(*p)就是一个const int,不可改变值,因为指向的是const

 

是否可以*p++;

 

 

 

是否可以P++;

 

 

++在前面也同样。

    int *p;
    cout << *p; // 报错,一定要先赋值后使用
    void *p1;  // 可以指向任何类型,其他要指向相同类型
23.3二级指针,二级指针变量存储的是一级指针变量的地址
int x = 0;
int *p = &x;
int **pp = &p;  // 二级指针指向的只能是一级指针变量的地址,*p是p指向的值,而&p是p的地址,不是x的地址
23.4.0指针数组,  int *a[5];  a[4] = &x;数组元素的值是地址
23.4.1指向数组的指针int (*a)[5]; a是二维指针,只能指向一维指针的地址
int (*a)[5];
int b[5];
a = &b;  // 指向数组的指针,只能指向数组元素为5的,其他不行。
// *a是b[0]的地址, **a是元素b[0]的值

23.4.2指向二维数组的指针,二维数组的数组名是一个二级指针

int (*a[2])[3];  a[0] 指向长度为3的int型数组的指针变量,就是上面那个的数组版。 
int (*a[2])[3];
int b[2][3] = {{1,2,3},{4,5,6}};
a[0] = b;
cout << **a[0];  // 等于b[0][0];
cout << **(a[0] + 1);  // 等于*(a[0]+1)是a[1][0]的地址
23.5new和delete处理
int *a = new int;
int *b = new int(4);
delete a;  // 释放单个
int *c = new int[4];
delete []c;  // 释放数组
23.6指针不要做的操作
将两个指针相加/将常数和指针相乘/将指针除以常数
24-字符,字符串
字符串数组,'\0'结尾,不然输出会有乱码,就不是字符串数组了,可以通过指针整个操作
sizeof() //求内存
strlen() //求到\0有多少个 \0不包括
char a[50] = {'a','b','c','d'}; // 末尾自动补零
char a[] = {'a','b','c','d'}; // 末尾不自动补零,要一起输入才没事
char *a = "abcd"; // 自动补零,可是不可改动,只能整个指针改变指向
0’字符
0 结束标志
‘\0’ 结束标志
char *p最好用于比较p代表第一个字符,可以通过加加来移动
函数参数用char a[];
25-结构类型, 变量通过.索引,指针通过->索引
#include <iostream>
using namespace std;

struct DATE
{
    int year;
    int month;
    int day;
};
struct PERSON
{
    int id;
    char name[20];
    DATE birthday;
};

int main()
{
    PERSON person = {10001, "张", {1977, 12, 12}};
    PERSON *p_person;
    p_person = &person;
    cout << person.id << endl;
    cout << p_person->name << endl;
    return 0;
}
26-枚举类型enum 名字{标识符,标识符};
(1)枚举类型按常量处理,不能赋值
(2)枚举元素,没有赋值,重0开始,累加
(3)enum weekday{sun = 7, mon = 1, tue, wed, thu, fri, sat};  // tue重2开始
(4)常量可以强制转换为枚举类,就是常量,可以进行运行运算,enum 的对象可以赋值给整型,会自动转换,但整型不可以赋值给enum对象,要强制类型转换。
weekday day;
day = weekday(1);
27-union联合体
在与硬件交互时常常需要用到
联合体占的内存大小是元素中占内存大小最大的那个的内存大小值
联合体可以嵌套在联合体中,也可嵌套在结构体中
用于包含不会同时出现的元素变量,这样就不会出现被修改,或者浪费内存了。
28-控制台输入输出
 
格式函数
非格式函数
类型 输入 输出 类型 输入 输出
char
scanf() //遇到空格结束,有两个一起
输入是不结束scanf("%d%d",&a,&b);
sscanf()格式输入
printf() char
getch()
getche()
getchar()
putch()
putchar()
int int    
float float    
string string gets() puts()
 
数据类型   格式控制符
整型
有符号短整型
无符号短整型
有符号长整型
无符号长整型
无符号十六进制
无符号八进制
%d或%I
%u
%ld
%lu
%x
%o
实型
浮点型
double型
%f
%lf
字符
有符号字符
无符号字符
%c
%c
字符串   %s
控制符
说明
数字 指定字段宽度的位数
. 区分字段宽度与精度的小数点
数字 指定精度的位数
-负号 表示在指定宽度内左对齐输出
 
  1. %-15.9lf // %在最前,整个输出占15个位置,9表示小数点输出9位
  2. sprintf(str, "%c %d",ch, i); //不用与屏幕输入输出
  3. gets从键盘接收到\n时就停止接收,并将\n换成\0
  4. getline等不是键盘或屏幕的操作
  5. 用lf于float类型会出现错误,
  6. 注意输出,如果双引号内的类型和外面的类型不同可能会出错.
  7. 输入的要记得加&,类型不对应也会出错,一直输入为0
29-函数
29.1-要改变到参数的值,要么用指针,或者引用。要将两个值交换就得如此
29.2-原型声明可以多次,定义只能一次
29.3-默认形参,顺序必须是从右向左的
int add(int x, int y = 5, int z = 6); // 从右开始,对
int add(int x = 1, int y = 5, int z); // 从左开始,错
int add(int x = 1, int y, int z = 6); // 不连续,错

29.4-函数可以返回指针,称为指针函数, int *f();   // 注意不要返回局部变量,因为函数结束,系统会销毁

29.5-函数返回引用 // 返回实际值,占用内存较大时,可以返回引用。返回的也不能是局部变量,
int &fun(int &x)  // 传进来的参数,修改后在返回,才是正确的使用方法
{
    return x;
}
29.6-内联函数,用于小巧函数,系统编译时,会将内联函数,用整个函数内容替换。
29.7-重载函数:c没有,重载是c++的概念
29.7.0-能够根据函数参数的个数和类型不同确定所要调用的函数
29.7.1-参数个数,或者参数类型,参数顺序不同算重载,而返回值不同,函数体不同都不算重载。
30-预处理命令
原理
1、宏从C保留下来,它与inline函数十分类似,只是没有进行类型检查,只是原样的展开
2、在编译之前,预处理器要先对宏定义进行检查,替换
3、宏可分为带参数与不带参数
4、宏定义可出现在程序中的任何位置。通常,将宏定义放在源程序文件开始部分。宏名的作用域为从宏定义开始到本源程序文件结束
5、宏存在的缺点可以靠inline内联函数来弥补,inline函数继承了宏的优点
6、就是把宏模版后面的所有包括括号都替换
7、#将后面的进行字符串操作,及加上双引号
8、##只是连接两个参数,没有加双引号
优点与不足:
1、给常量取一个容易记忆的名字
2、当某常量多次出现时,要修改可以只改一个地方
3、不需要用栈等,速率更快。没有函数调用的时间消耗
4、没办法修改。避免了const可能被修改报错的
5、在程序中上百次使用宏时,要上百次的替换,产生的扩展源代码很多,而函数上百次调用还是只占有一个空间
6、宏的内存开销可能比函数大,时间开销比函数小。
7、没有类型的检查与转换
8、宏不能够递归
9、宏有碍调试,对变量名等可能造成破坏。
10、宏没有地址
好习惯:
1、整个宏扩展应该包含在括号内
2、大写
3、给每个参数都加括号,在运算中
用法:
1、实现最大值
#define MAX(x,y) (((x) > (y) ? (x) : (y)))
最外层的括号不可省略
2、宏参数的连接
3、定义运算符
#define AND &&
#define OR ||
4、替换条件
#define CONFITION  (a > 25 AND a < 5)
5、替换c语言语句
#define OUT printf("I can use hong");   //有分号
6、可以分成多行用反斜线 \
#define MM cout << "mm" \                        << endl;
MM    //不用分号。
cout << "mm" << endl;
7、VS2008查看预处理后的文件
项目属性--配置属性--C++--预处理器--生成预处理文件--/p   
此时将无法编译程序,obj找不到 
8、和条件编译合作避免重复编译
#ifndef _HEAD_H
#define _HEAD_H
#endif
9、整型变字符串
#define STR(s) #s
string s = STR(43);
10、科学计算法,十位个位的连接
#define CONS(a,b) (int)(a##e##b)
cout << CONS(1,4);     //10000
如果去除e,则相当于14;
11、得到数组所含元素个数
#define ARR_SIZE(a) (sizeof((a)) / (sizeof((a[0])))
12、得到一个字的高位低位字节
#define WORD_LO(x) ((byte)((word)(x) & 255))
#define WORD_HI(x) ((byte)((word)(x) >> 8))
13、宏的嵌套
#define NUM 2
#define P NUM*2
问题:
1、不可用分号。
2、#define 宏模版 宏扩展  //宏模版与宏扩展之间一定要有空格隔开
3、宏模版与参数之间不能有空格
4、注意运算优先级的影响
5、实参可以为++i,或者其他,但是要注意++i是否用了多次
6、实参也可以是函数,也要注意函数是否多次调用
7、"内"双引号内不置换
例子
#define WARN_IF(EXP) \
do{ if (EXP) \
fprintf(stderr, "Warning: " #EXP "\n"); } \
while(0)
那么实际使用中会出现下面所示的替换过程:
WARN_IF (divider == 0);
被替换为
do {
if (divider == 0)
fprintf(stderr, "Warning" "divider == 0" "\n");
} while(0);
14、条件编译
#ifdef/#ifndef 标识符
程序段
#endif

#ifdef/#ifndef 标识符
程序段1
#else
程序段2
#endif
#define toString(s) #s // 无论s为什么都会变成字符串;
#define lian(x,y) x ## y // 无论x,y传入的是什么,都会被连接在一起,连接后的数如果没有意义就会报错
#define absolute_value( x ) ( ((x) < 0) ? -(x) : (x) ) // 解决了我一问题,就是怎么让一个数取相反数
#error 语句 // 无论语句是否正确都在这里停止
#line _LINE__ // 用于行数改变的,没什么用处
#undef //取消某个已经定义的宏
__LINE__ 和 变量表示的正在处理当前行和. //整数
__FILE__正在处理当前文件 // 字符串形式
__DATE__ 变量表示当前日期,格式为month/day/year(月/日/年). // 字符串形式
__TIME__ 变量描述当前的时间,格式为hour:minute:second(时:分:秒). // 字符串形式
1、预处理指令有四种:
(1)宏指令
(2)文件包含
(3)条件编译
(4)其他指令
 
宏指令的好处:
1、可读性增强,WIDTH 代替10;就可以知道这个是高了。
2、在编译之前会生成宏扩展源代码,可以打开,用于查出错误。后缀名为 .I
#define MAX 5
char a[MAX] = "abcd";
#define sout(s) printf(#s"\n") //不用每次输出文字加双引号,这种
#define sout(s,x) printf(#s"\n",x) // 要加参数 sout(1,2); = printf("1\n", 2);





posted @ 2013-09-05 15:12  陈卓生  阅读(297)  评论(0编辑  收藏  举报