黑马程序员——1、C语言(基础语法)

来源:互联网 发布:海南软件生态园 编辑:程序博客网 时间:2024/05/15 02:10

---------------------- Java培训、Android培训、iOS培训、.Net培训,期待与您交流! ---------------------


一、标识符、关键字及注释

  1. 标识符

标识符,就是在程序中用来标识某些的符号,标识的目的就是为了将这些东西区分开来。C语言是由函数构成的,一个C程序中可能会有多个函数,为了区分这些函数,就给每一个函数都起了个名称。函数的名称就是标识符的一种。除了函数,以后还会学到“变量”这个概念,变量的名称也是标识符。

命名规范: 

  • 标识符是由字母、数字和下划线"_"构成的序列。
  • 不能以数字开头
  • 大写字母和小写字母是不同的。
  • 不可以使用关键字作为标识符。
  • 尽量起一些有意义的名字,推荐以驼峰形式命名。

  2.关键字

关键字,也叫做”保留字“。

在C语言中,关键字用来表达一些具有特殊含义的符号。下列标识符被保留作为关键字,且不能用于其它途径:

autodoubleintstruct

breakelselongswitch

case enum registertypedef

charexternreturnunion

constfloatshortunsigned

continueforsignedvoid

defaultgotosizeofvolatile

do ifstaticwhile

  3.注释

为了方便程序员之间的交流,可以用注释来注解、解释一段程序或代码的意思。

两种注释方法:

  • 单行注释:以两个正斜杠开头//,只能注释一行,即//开始到这一行的结尾都是注释的内容。
  • 多行注释:/*开头,以*/结尾,/**/中间都是注释的内容。

注释的作用:

  • 被注释的代码不会参与编译。也就是说在编译过后的.o文件中,并没有注释这部分的代码内容,之后的可执行问就更不会有了。
  • 注释有检查代码的作用。也就是说可以把一段代码注释了之后再次运行,得到的结果跟之前结果相比较,看看结果又什么不同,可以清楚这段代码的作用。
  • 排除错误。在调试阶段,大部分人都会使用注释掉一段代码来,排除某些错误,查看出错的代码在哪一段。

注释的注意事项:

  • 单行注释可以嵌套单行注释、多行注释; 多行注释可以嵌套单行注释;多行注释不能嵌套多行注释;单行注释也不能够嵌套多行注释的/*。
  • 注释不能够出现在字符串字面值或字符字面值中。


二、数据类型、常量和变量

  1.基本数据类型

(数据类型的大小是在Xcode5编译器下的大小)

 (1)整型

int4个字节%d、%i
long/long int8个字节%ld
short/short int2个字节%d、%i
unsigned/unsigned int4个字节%zd、%lu

signed/signed int4个字节%d、%i

  (2)浮点型

float4个字节%f

double8个字节%f

  (3)字符型

char1个字节%c、%d

(注:char类型保存在内存中是它的ASCII值)

  2.构造类型

  (1)数组

1》只能由同一种类型的数据组成

2》定义:数据类型 数组名[元素个数]

int ages[3]; // 定义了一个元素个数为3的int类型数组

  (2)结构体

1》可以有不同类型的数据组成

2》先定义类型,再利用类型定义变量

struct Person{int age;char *name;};struct person p = {25, "libai"};

  3.指针类型

void * 占8个字节大小

  (1)变量的定义

int *p;

  (2)间接操作变量的值

int a = 10;p = &a;*p = 20;

  4. 枚举类型

使用场合:当一个变量只有几个固定的取值的时候。

enum Sex{sexMan,sexWoman};Sex sex = sexMan;

  5. 空类型

void占1个字节大小

  6. 常量

常量,用来表示一些固定的数据。一但常量被定义,程序中不能修改常量的值。

常量的分类:

  (1)整型常量(int)

整型常量有一串数字组成,包含了所有的整数。如果它以o或O开头,则为八进制数,否则为十进制数;如果它以0b或0B开头,则为二进制数;如果它以0x或0X开头,则为十六进制数。

整型常量如果以字母u或U为后缀,则表示它是一个无符号数;如果以字母l或L为后缀,则表示它是一个长整型数;如果以祖母UL为后缀,则表示它是一个无符号长整型数。

  (2)字符常量(char)

字符常量是用单引号引起来的一个字符构成,如'c'。

字符常量不包括字符 ' 和换行符,可以使用以下转义字符序列表示这些字符以及其它一些字符

换行符NL(LF)\n反斜杠\\\横向制表符HT\t问号?\?纵向制表符VT\v单引号'\'回退符BS\b双引号"\"回车符CR\r八进制数ooo\ooo换页符FF \f十六进制数hhh\xhh响铃符BEL\a   

转义序列\ooo由反斜杠后跟1个、2个或3个八进制数字组成,这些八进制数字用来执行所期望的字符的值。\0(其后没有数字)便是一个常见的例子,它表示字符NULL。转义序列\xhh中,反斜杠后面紧跟x以及十六进制数字,这些十六进制数用来指定所期望的字符的值。数字的个数没有限制,但如果字符值超过最大的字符值,该行为是未定义的。

  (3)浮点常量(double/float)

浮点常量由整数部分、小数点、小数部分、一个e或E、一个可选的带符号整数类型的指数和一个可选的表示类型的后缀(即f、F、l或L之一)组成。浮点常量的类型由后缀确定,F或f后缀表示它是float类型;l或L后缀表示它是long double类型;没有后缀则表明是double类型。

浮点型常量的分类:

* double:双精度浮点型,其实就是小数。

* float :单精度浮点型,也是小数,但比double的精确度低,也就是说所能表示的小数位数较少。

区分double和float:float型数据都是以f为后缀的,double则没有后缀。

  (4)字符串常量

将一个或多个字符用双引号("")引起来,这样就构成了字符串常量,如"李白"。

  (5)枚举常量

声明为枚举类型的标识符是int类型的常量,叫枚举常量。(之后再枚举类型中详细说明

  7. 变量

当一个数据的值需要经常改变或者不确定时,就应该用变量来存储。

  (1)变量的分类

  ***根据变量的作用域分类:

1》局部变量

定义:在函数(代码块)内部定义的变量(包看看函数的形参)。

作用域:从定义变量的那一行开始,一直到代码块结束。

生命周期:从定义变量的那一行开始分配存储空间,代码块结束后,就会被回收。

初始值:没有固定的初始值。

2》全局变量

定义:在函数外面定义的变量。

作用域:从定义变量的那一行开始,一直到文件结尾(能被后面所有函数共享)。

生命周期:程序一启动就会分配存储空间,程序退出时才会被销毁。

初始值:默认初始值为0。


  ***根据变量的存储类型分类:

1》自动变量

定义:存储在堆栈中的变量。

auto 变量类型 变量名;

默认情况下所有的局部变量都是自动变量。

生命周期:定义自动变量那行开始,一直到代码块(函数)执行结束,自动变量自行销毁。

2》静态变量

定义:存储在静态内存中的变量,不属于堆栈。

static 变量类型 变量名;

所有的全局变量都是静态变量;被关键字static修饰的局部变量也是静态变量。

生命周期:静态变量在程序运行之前创建,在程序的整个运行期间始终是存在的,知道程序结束。

3》寄存器变量

定义:存储在硬件寄存器中的变量。

默认情况下,自动变量和静态变量都是放在内存中的,而寄存器变量存放在寄存器中,效率比二者高。

register 自动变量;

只有自动变量才能是寄存器变量,全局变量、静态变量都不行。

寄存器变量只限于int、char和指针变量。

生命周期:跟自动变量一样。

一般只有将一些频繁使用的自动变量定义为寄存器变量,这样程序尽可能地为他分配寄存器,提高效率。

  (2)定义变量

任何变量都要在使用之前,先对其进行定义。定义变量的目的是在内存中分配一块存储空间给变量。方便以后存储数据。如果定义了多个变量,就会为这多个变量分别分配不同的存储空间。

定义变量格式如下:

变量类型变量名;

int age;

变量名属于标识符,不同的变量类型的变量所占的存储空间不同。

变量的第一次赋值,称之为“初始化“。

初始化的2中形式:一是先定义,后初始化;二是定义的同事进行初始化操作。

  (3)变量的注意事项

1》可以修改变量里面的值,每次赋值都会覆盖原来的值;

2》没有初始化的变量不要拿来使用;

3》变量名不能重复;

4》注意变量的作用域(前面讲过的局部变量和全局变量)。


三、基本运算

  1. 算术运算符

一元算术运算符+(正)、-(负)和二元算术运算符+、-、*、/、%(模运算)。

注:模运算(%)只能用于整数,不能应用于float或double类型;在有负操作数的情况下,模运算的正负取决于具体机器的实现(一般取决于%左侧的整数数值)。

  2. 关系运算符

关系运算符包括==、!=、<、<=、>、>=。

关系运算符的结果只有2种:如果条件成立,结果为1(真);如果条件不成立,结果为0(假)。

  3. 逻辑运算符

逻辑运算的结果只有2个:“真“为1,”假“为0。

C语言规定:任何非0值都为“真”,只有0才为“假”。

(1)逻辑与 &&

条件A && 条件B

只有当条件A和条件B都成立时,结果才为1(真),其余情况的结果都为0(假)。

逻辑与的结合方向:”从左往右“。

(2)逻辑或 ||

条件A || 条件B

条件A或条件B只要有一个成立,结果就为1(真);只有条件A和条件B都不成立,结果才为0(假)。

逻辑或的结合方向:”从左向右“。

(3)逻辑非 !

! 条件A

对条件A进行取反:若条件A成立,结果就为0(假);若条件A不成立,结果就为1(真)。

逻辑非的结合方向:”自右向左“。

  4. 自增运算符与自减运算符

自增运算符++使操作数递增1,自减运算符使操作数递减1。

前缀运算符:++n / --n,先将n的值递增或递减,然后再使用变量n的值。

后缀运算符:n++ / n--,先使用变量n的值,然后再将n的值递增或递减。

注:常量的自增或自减是非法的,如:(i + j)++ 。

  5. 按位运算符

位操作运算符只能作用于整数操作数,即只能作用于带符号或无符号char、short、int、long类型。

&按位与(AND)|按位或(OR)^按位异或(XOR)>>左移<<右移~按位求反

(1)按位与 &

按位与运算符&常用于屏蔽某些二进制位:n = n & 1;

 二进制中,与1相&就保持原位,与0相&就为0。

(2)按位或 |

按位或运算符|常用于将某些二进制位置1:x = x | SET_ON;

(3)按位异或 ^

按位异或^运算符,当两个操作数的对应位不同时置1,否则置0。

规律:a^b^a = b    a^a = 0

(4)左移 << 

移动的位数由右操作数指定(右操作数的值必须是非负值)。

unsigned类型:右边空出部分补0

signed类型:某些机器将左边符号位保持不变,只丢弃最高位(算术移位);有些机器将左边符号位用最高位填补(逻辑移位)。右边空出部分还是补0。

(5)右移 >>

移动的位数由右操作数指定(右操作数的值必须是非负值)。

unsigned类型:左边空出部分补0

signed类型:某些机器将左边空出部分用符号位填补(算术移位);有些机器将左边空出部分用0填补(逻辑移位)。

(6)按位取反 ~

对整数a的各二进位进行取反,符号位也取反(0变1,1变0)

/* getbits: get n bits from position p */unsigned getbits(unsigned x, int p, int n){// 这里假定最右边第一位是第0位  return (x >> (p+1-n)) & ~(~0 << n); <span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">//~0这里用得好</span>} 

  6. 赋值运算符

(1)简单赋值 

int a = 10;

(2)复合赋值

int a *= 4 + 5;

  7. 三目运算符

int a = 5 ? 10 : 2;

  8. 运算符优先级

优先级

描述

运算符

1

括号

()、[]、->、.

2

正负号

+、-

3

自增自减,非

++、--、!

4

乘除,取余

*、/、%

5

加减

+、-

6

移位运算

<<、>>、>>>

7

大小关系

>、>=、<、<=

8

相等关系

==、!=

9

按位与

&

10

按位异或

^

11

按位或

|

12

逻辑与

&&

13

逻辑或

||

14

条件运算

?:

15

赋值运算

=、+=、-=、*=、/=、%=

16

位赋值运算

&=、|=、<<=、>>=、>>>=



四、进制

进制,一种计数的方式,数值的表示形式。

  1. 二进制

(1)特点:只有0和1,逢2进1

(2)书写格式:0b或者0B开头

(3)使用场合:二进制指令\二进制文件,变量在内存中就是二进制存储

(4)n为二进制位所能表示的数据范围(不考虑负数):0~2的n次方-1

  2. 八进制

(1)特点:0~7,逢八进一

(2)书写格式:0开头

3. 十六进制

(1)特点:0~F,逢十六进一

(2)书写格式:0x或者0X开头


五、变量内存分析

  • 内存以“字节”为单位
  • 内存由大到小寻址
  • 只存储二进制形式

  1.变量存储

每个变量都有地址:第一个字节的地址就是变量的地址

输出地址的两种格式符:%x(以无符号的形式输出十六进制)和%p

变量所占的字节与类型有关,与编译器环境有关

  2.取值范围




六、typedef

typedef:为各种数据类型定义一个别名。

  1. typedef与基本数据类型

typedef int MyInt;

  2. typedef与指针

typedef char * String;//给指针类型char *起一个新的类型名String

  3. typedef与结构体

typedef struct Student{    int age;    String name;} Mystu;Mystu stu = {10, "wangwu"};

  4. typedef与枚举

typedef enum Sex{    Man,    Woman} MySex;;MySex s = Man;

  5. typedef与指向结构体的指针

typedef struct Person{    int age;} * PersonPoint;struct Person person = {12};PersonPoint p = &person;

  6. typedef与指向函数的指针

typedef int (*MyPoint)(int, int);int sum(int a, int b){    return a+b;}MyPoint p = sum;p(10, 2);

  7. typedef和#define的区别

#include <stdio.h>typedef char * String;#define String2 char *int main(){    //s1, s2都是char *    String s1, s2;    //String s1;    //String s2;        //s3才是char *指针,s4是char    String2 s3, s4;    //char *s3;    //char s4;        return 0;}

结论:以后给类型起别名,最好还是用typedef,而不是#define。


0 0
原创粉丝点击