黑马程序员--01C语言基础

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

              

                                                                             第一讲:关键字/标识符/注释



1.什么是关键字

关键字就是C语言提供的有特殊含义的符号,也叫做保留字

C语言一共提供了32个关键字,这些关键字都被C语言赋予了特殊含义

auto double int struct break else long switch

case enum register typedef char extern return union

const float short unsigned continue for signed void

default goto sizeof volatile do if while static


2.关键字的特征

全部都是小写


3.什么是标识符

标识符就是在程序中自定义的一些符号和名称。要跟关键字区分开来:关键字是C语言默认提供的符号,标识符是程序员自定义的,比如函数的名称

命名规则(一定要遵守):

 只能由26个英文字母的大小写、10个阿拉伯数字0~9、下划线_组成  严格区分大小写,比如testTest2个不同的标识符 

不能以数字开头 

不可以使用关键字作为标识符


4.注释

注释有两种,单行注释与多行注释:

单行注释,//

<span style="font-size:14px;">int main() // 主函数(空格+双斜杠+空格)
{
   printf("hello world");
   return 0;
}
</span>
多行注释,

/*

.......

*/

注意:单行注释和多行注释可以相互套用,但多行不能套用多行


                                                                                第二讲:数据类型/常量/变量

1.数据分类(存储)

计算机中存储的数据可以分为两种:静态数据和动态数据。

 静态数据是永久性数据,存在硬盘,比较大,计算机关闭再开启,依然存在,比如,文档或者照片;

动态数据时临时数据,程序运行过程中产生,计算机关闭后临时数据被清除,比如程序被加载到内存,或者运行过程中产生的数据,程序停止,数据小消失。


2.C语言数据分类

    C语言中将数据分为常量和变量。

    2.1常量

    常量就是固定不变的量,又分为四类:

    1> 整型常量(int)

         包括了所有的整数,比如627109256-100-289

    2> 浮点型常量(float\double)

          浮点型常量分为doublefloat两种数据类型

          double:双精度浮点型,其实就是小数。比如5.43-2.30.0等(注意,0.0也算是个小数)

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

          为了跟double区分开来,float型数据都是以f结尾的,比如5.43f-2.3f0.0f。需要注意的是,绝对不能有10f这样格式的,编译器会直接报错,只             有小数才允许加上f

    3> 字符常量(char)

          将一个数字(0~9)、英文字母(a~zA~Z)或者其他符号(+-!?等)用单引号括起来,这样构成的就 'F''+''$'等。

         注意:单引号只能括住1个字符,而且不能是中文字符,下面的写法是错误的:'abc''123456'''

     4 > 字符串常量

         将一个或者多个字符用双引号("")括起来,这样构成的就是字符串常量。比如"6""""哇哈哈""abcd""my_car4"

      2.2变量

           当一个数据的值需要经常改变或者不确定时,就应该用变量来表示。比如游戏积分。

           变量的定义和初始化

           变量要先定义类型再使用int   a;

           在C中,不初始化直接使用可以运行,并不会提示错误,但是如果该变量是全局变量,系统会自动赋值(整数会赋值为0)但如            果是局部变量(定义        在函数内部的变量),系统会随机分配一个值,不一定是0,(因为定义时只是随机分配了一个存储              空间,所以有可能得到一个垃圾数据)

           所以要记得初始化

          int  a = 88;

          格式

           变量类型  变量名;

            比如int num;     变量名属于标识符


        char类型的变量

char类型的变量在内存中存储为一个字节的二进制码, 可以以字符或者整数的形式打印输出.可以和0~127的整数一一对应.   

ASCII码表把0~127之间的数字一一对应一个字符,比如'A''B''c''d'','*'等等,根据这张表,就可以查出内存中存储的是哪个字符.

每一个字节中的内容都是8个二进制码,可以用%d输出当前字节对应的整数值 (-128~127),也可以用%c输出当前字节对应的字符,当然有的字符输出为空字符.

 char c = 'A'; 

字符在内存中存储它的ASCII码值对应的二进制数.所以 'A' 在内存中相当于存储为65,因为 char占一个字节, 8位二进制数,所以存储为 0100 0001.

 

字符和整数的对应关系

ASCII码表中的字符和0~127之间的整数有一一对应的关系

字符可以用十进制数打印,值为它的ASCII码值

//字符可以用%d%c打印

printf("%d: %c\n", 'A', 'A');

整数也可以以字符形式打印,打印出的是它的最末8位对应的整数在ASCII码表中对应的字符 (如果最末8位代表的数字在0~127范围内的话)

// int也可以用%d%c打印

printf("%d: %c\n", 67, 67); 

 

字符和数字可以加加减减

char c2 = 'A' + 32;

printf("%d: %c\n", c2, c2);

 

//char c4 = A; 这个不行是因为char后边要跟一个字符,A是一个变量,应该加上单引号
    //char c4 = "A"; 这个不行是因为,char后边跟字符,“A”是一个字符串
    
    /*
     swith()
     {
       case(65)
       case('A')
     }这样不对,是因为A就是65
     */
    
    char c = 'A'+32;
    
    int c1 = 6; // 本身就是ACSII
    
    char c2 = '6'; // 6在这里代表字符,他对应的ACSII值事54
    
    char *c3 = "6"; // 字符串
    
    NSLog(@"%d-%c-%d-%d-%s",c,c,c1,c2,c3);
    
    NSLog(@"%c",65); // 这个打印出来就是A
    
    NSLog(@"%d",' ');
    
    NSLog(@"\\"); // 输出斜杠的方法

特殊字符

(转义字符):    '\'通常和它后面的字符合成为一个转义字符

'\n'  换行符

'\t'  TAB

'\\'  反斜线字符

'\''  单引号字符

'\"'  双引号字符

'\0'  空字符

这些虽然看起来是两个字符,但其实都是一个字符,可以打印出它们的ASCII码值:

printf("%d\n", '\n');    // 10

print("\");  //错误.可以发现后面几个字的颜色都是字符串的颜色,因为第二个"和前面的\结合为输出"字符了.所以还在等着下一个"来结束字符串.


变量在内存中的存储


内存空间以字节为单位.每个字节有地址,地址一般以16进制表示.

所有数据在内存中都是以二进制形式存储. 一个字节存8位二进制数.

不同的变量类型占据的字节数不同,与编译器有关

变量类型

16位编译器

32位编译器

64位编译器

char

1

1

1

int

2

4

4

float

4

4

4

double

8

8

8


注意:

变量在内存中存储时,会优先分配地址大的字节来存储变量的内容,存放数据也是由大到小。但是变量的起始地址是它的最小地址 (最后一位的地址). 

比如定义 int n1 = n2 = 12; 在内存中这么存储:

地址

变量

内容

0xffc9

n1

0000 0000

0xffc8

n1

0000 0000

0xffc7

n1

0000 0000

*0xffc6*

n1

0000 1100

0xffc5

n2

0000 0000

0xffc4

n2

0000 0000

0xffc3

n2

0000 0000

*0xffc2*

n2

0000 1100


查看变量在内存中的起始地址:

printf("%p", &a);        //通常使用的方式

printf("%x", &a);

 

查看变量在内存中占据的字节数:

printf("%d", sizeof(a));    //打印变量a占用的字节数

附:

基本类型汇总:

空类型:void

基本数据类型:int, float, double, char

构造类型:数组[],结构体struct,共用体union,枚举enum

指针类型:*p

       

                                                                                            第三讲:scanf函数

1.用法

int age;

scanf("%d", &age);scanf函数时,会等待用户的键盘输入,并不会往后执行代码。scanf的第1个参数是"%d",说明要求用户以10进制的形式输入一个整数。这里要注意,scanf的第2个参数传递的不是age变量,而是age变量的地址&age&C语言中的一个地址运算符,可以用来获取变量的地址

输入完毕后,敲一下回车键,目的是告诉scanf函数我们已经输入完毕了,scanf函数会将输入的值赋值给age变量


2.注意

1.scanf函数接收3个数值,每个数值之间用中划线-隔开

scanf("%d-%d-%d", &a, &b, &c);

3%d之间是用中划线-隔开的,因此我们在每输入一个整数后都必须加个中划线-,比如这样输入,不然在给变量赋值的时候会出问题

数值之间的分隔符是任意的,不一定要用中划线-,可以是逗号、空格、星号*、井号#等等,甚至是英文字母

2.scanf函数接收3个数值,每个数值之间用空格隔开

scanf("%d %d %d", &a, &b, &c);

3%d之间是用空格隔开的,我们在每输入一个整数后必须输入一个分隔符,分隔符可以是空格、tab、回车

3.scanf的第一个参数中不要包含\n,比如scanf(“%d\n”, &a); 这将导致scanf函数无法结束


3.scanf函数与gets函数比较

在接收字符串的时候,他们都会在结尾自动添加/0,所不同的是,scanf认为空格是/0,而gets认为回车时/0.这就意味着你无法用scanf接受一个英文句子作为数组内容,因为它一旦发现了空格就会认为这个句子已经结束了

<span style="font-size:14px;">int main() // input:I have a dream,output 'I'
{
    char a[1024];
    
    scanf("%s",a);
    
    NSLog(@"%s",a);
    
    return 0;
}</span>

因为你输入中I have ,scanf 只会接收到I,方法就是要把scanf换成gets


                                                                      第四讲:基本运算


1.算术运算

C语言一共有34种运算符,包括了常见的加减乘除运算

加法运算+

除开能做加法运算,还能表示正号:+5+90

减法运算-

除开能做减法运算,还能表示符号:-10-29

乘法运算*

注意符号,不是x,而是*

除法运算/

注意符号,不是÷,也不是\,而是/

整数除于整数,还是整数。1/2的值是0,这个并不是二分之一

取余运算%

%两侧只能是整数正负性取决于%左侧的数值

注意

自动类型转换

int a = 10.6;

int b = 10.5 + 1.7;

自动将大类型转换为了小类型,会丢失精度

自动类型提升

int b = 10.5 + 10;

将右边的10提升为了double类型

double b = 1.0 / 2;

解决除法的精度问题

强制类型转换

double a = (double)1 / 2;

double b = (double)(1 / 2);


赋值运算  =

int a = 10 + 5;的运算过程

a = b = 10;的运算过程

等号左边不能是常量,比如10 = 11;

自增自减

a++++a,都等价于a = a+1

自减运算符。如a----a,都等价于a = a-1

++aa++的区别

++a自身先加一然后再使用  a++先使用本身再加一


2.关系运算(比较运算)

关系运算符中==!=的优先级相等,<<=>>=的优先级相等,且前者的优先级低于后者:2==3>1

关系运算符的结合方向为从左往右 4>3>2

关系运算符的优先级小于算术运算符:3+4>8-2


3.逻辑运算

逻辑运算的结果只有2个:10


&&逻辑与

格式条件A && 条件B”

结果

只有当条件A和条件B都成立时,结果才为1,也就是;其余情况的结果都为0,也就是。因此,条件A或条件B只要有一个不成立,结果都为0,也就是

运算过程

总是先判断条件A是否成立

如果条件A成立,接着再判断条件B是否成立:如果条件B成立,条件A && 条件B”的结果就为1,即,如果条件B不成立,结果就为0,即

如果条件A不成立,就不会再去判断条件B是否成立:因为条件A已经不成立了,不管条件B如何,条件A && 条件B”的结果肯定是0,也就是

结合方向自左至右比如表达式 (a>3) && (a<5)

注意

C语言规定:任何非0值都为,只有0才为。因此逻辑与也适用于数值。比如 5 && 4的结果是1,为-6 && 0的结果是0,为

 

逻辑或

格式条件A || 条件B”

结果

当条件A或条件B只要有一个成立时(也包括条件A和条件B都成立),结果就为1,也就是;只有当条件A和条件B都不成立时,结果才为0,也就是

 运算过程

总是先判断条件A是否成立

1如果条件A成立,就不会再去判断条件B是否成立:因为条件A已经成立了,不管条件B如何,条件A || 条件B”的结果肯定是1,也就是

2如果条件A不成立,接着再判断条件B是否成立:如果条件B成立,条件A ||条件B”的结果就为1,即,如果条件B不成立,结果就为0,即

结合方向自左至右比如表达式 (a<3) || (a>5)

 注意

 C语言规定:任何非0值都为,只有0才为。因此逻辑或也适用于数值。比如 5 || 4的结果是1,为-6 || 0的结果是1,为0 || 0的结果是0,为

 

!逻辑非

格式“!条件A”

结果

其实就是对条件A进行取反:若条件A成立,结果就为0,即;若条件A不成立,结果就为1,即。也就是说:真的变假,假的变真。

结合方向自右至左比如表达式 ! (a>5)

 注意

C语言规定:任何非0值都为,只有0才为。因此,对非0值进行逻辑非!运算的结果都是0,对0值进行逻辑非!运算的结果为1!5!6.7!-9的结果都为0!0的结果为1

优先级

逻辑运算符的优先级顺序为:小括号() >负号 - > ! > 算术运算符 > 关系运算符 > && > ||


三目运算符

ab :c    a为真b,a为假是c


位运算

&按位与

只有对应的两个二进位均为1时,结果位才为1,否则为0

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

|按位或

只要对应的二个二进位有一个为1时,结果位就为1,否则为0

^按位异或

当对应的二进位相异(不相同)时,结果为1,否则为0

 规律

1  二进制中,与0^就保持原位,所以相同整数相^的结果是0。比如5^5=0

2  多个整数相^的结果跟顺序无关。比如a^b^c=a^c^b

3  0异或为本身0^9=0

结论:4 a^b^a =b  ( a^b^a = a^a^b = 0^b =b)


~取反

对整数a的各二进位进行取反,符号位也取反(0110

<<左移

把整数a的各二进位全部左移n位,高位丢弃,低位补0。左移n位其实就是乘以2n次方

由于左移是丢弃最高位,0补最低位,所以符号位也会被丢弃,左移出来的结果值可能会改变正负性

>>右移

把整数a的各二进位全部右移n位,保持符号位不变。右移n位其实就是除以2n次方

为正数时,符号位为0,最高位补0

为负数时,符号位为1,最高位是补0或是补1取决于编译系统的规定




运算总结

 运算符总结

算术运算符: +   -   *   /   %   %要求两边都是整数

关系运算符: <  <=  ==  >  >=  !=运算结果为10

C语言中,没有boolean类型,只有数字0为假,其它所有值都为真。所以可以用任何表达式作为条件,只要值不为0,就判断为真

逻辑运算符  && || !同样是返回1或者 0

赋值运算符     =   +=  -=   *=   /=    %=  

自增自减运算符   ++ --

逗号运算符用于连接表达式,并返回最后一个表达式的值

比如 a = 3 + 4, b = 3 * 4;逗号只是用于连接表达式,相当于用;分隔

但是逗号表达式有返回值,返回最后一个表达式的值,比如上一个式子这个表达式的值为12

比如int a = 2;  int c = (++a, a *= 2, b = a * 5);那么c的值为30,上面的式子,如果没有括号,那么c的值为3

三目运算符  (条件运算符)a ?b  :c

比如  int a = (b > 0) ? 1 : -1;

 sizeof运算符

返回一个变量在内存中所占的字节数,返回类型为size_t(是个无符号整数)比如size_t size = sizeof('A'); 注意这里是个陷阱哦,char ‘A’会被转化为整数,所以这里相当于sizeof(65),所以返回值是4而不是1喔,怎么办呢?char c = 'A'; size_t size = sizeof(c); 这样就是1


 运算符优先级总结  (优先级由上到下依次降低)

1.初等运算符            

结合方向:从左到右()  [  ]   ->   .    优先级相同

2.单目运算符       

结合方向:从右到左    !   ~   ++    --     -   (类型)(类型转换符)    *(指针运算符)  &  sizeof  优先级相同

3.算数运算符(双目运算符) 

结合方向:从左到右*  /  % 相同    +  -  次之     <<   >> 次次之 

4.关系运算符(双目运算符) 结合方向:从左到右<  <=  >  >= 相同      ==   !=  次之

5.位运算符(双目运算符) 

结合方向:从左到右&  ^  |  优先级一次降低

6.逻辑运算符  (双目运算符) (不包括!因为!是单目运算符优先级高)

结合方向:从左到右&&     ||  优先级依次降低

7.条件运算符  (三目运算符)

结合方向:从右到左  ?  :   

8.赋值运算符 (双目运算符) 

结合方向:从右到左=  +=  -=  *=   /=  %= >>=  <<= &= ^= |=

        9.逗号运算符  (),

结合方向:从左到右  


求值顺序总结

优先级:决定相邻的多个不同运算符之间的执行顺序

结合性:决定操作数(参与运算的变量,常量,字面值)与相邻的多个相同优先级的运算符之间的结合顺序

比如2+3*5      优先级*高于+  2+3*5

2+3-4      依靠结合性  由于+-)是自左向右结合因此+3结合

求值顺序优先级和结合性决定且只决定表达式如何加括号而不决定表达式的求值顺序,在C语言中,表达式的求值顺序一般是任意的。


C语言中对4个运算符规定了表达式的求值顺序

a&&b:   先求a,只有a为真才会求b.

a || b  :先求a,只有a为假才会求b.

a,b,c  :逗号运算符,从左到右一次求a,b,c的值

特别注意:函数的参数列表中分割多个参数的逗号不属于逗号表运算符

 所以 f(a++,a)中先算a++还是a并不一定。

a ? b  :  c只有a为真才会求b的值,只有a为假才会求c的值

比如  {

int   x=3,y=2;

x>y ? 10 : ++y>2 ? 20 :30

}

结果为:   10       

         x>y ? 10 : ++y>2 ? 20 :30  相当于(x>y ? 10 :((++y>2 ? 20 :30


补充1:


类型修饰符

变量占据的字节数决定了变量的取值范围


long short来修饰 int占据的字节数

不同类型所占的字节数在不同的编译器下有所不同, ANSI \ ISO制定了以下规则:

      shortint至少为16(2字节)

      long至少为32(4字节)

      short的长度不能大于intint的长度不能大于long

      char一定为为8(1字节).  char是我们编程能用的最小数据类型

 long int 等价于 long

unsigned signed修改 int最高位的含义

signed int最高位是符号位,取值范围是 -2^31 ~ 2^31-1,是说int可以取负,int本来就是有正数和附属,所以这样来修饰是废的

unsigned int最高位是数字位,取值范围是 0 ~ 2^32-1,输出用 %u 占位符

因为 int本身最高位就是符号位,所以默认就是 signed.

 注意

long a = 0l;等价于 long int a = 0l;

unsigned b = 0;等价于 unsigned int b = 0;

两种修饰符可以一起使用:

short unsigned a = 0L;     //正确

同种修饰符不可以一起使用:

long short int a = 0;        //

sizeof()函数返回值类型是 unsigned long


进制 

进制是一种计数方式,0开始,x进位.不同进制其实就是同一个数字的不同写法.

软件开发最常用十进制和二进制,也使用十六进制和八进制.

 

进制转换 

十进制数和其它进制数的相互转换:

十进制: 12 ( = 10 + 2)

二进制: 1100 ( = 8 + 4 + 0 + 0)

八进制: 14 ( = 8 + 4)

十六进制: C  ( = 12)

代码中的表示

   数字的进制表示  (字母大小写随意)

十进制无前缀数字        比如 12

二进制前缀0b              比如 0b1100表示这是一个二进制数,值是12,不是1100

八进制前缀0                比如 014表示这是一个八进制数,值是12,不是14

十六进制前缀0x           比如 0xc表示这是一个十六进制数,值是12,不是变量c的值

 数字的进制打印

十进制%d, %i        输出 12

二进制:

八进制%o            输出 014

十六进制: %x      


补充2:

计算字符串长度的时候

sizeof计算字符串长度,计算的是字节数,且包含/0
所以sizeof(“itcast”),就是7,因为包含/0
strlen(),计算字符数,而不是字数,不包含/0
strlen(“哈haha”),长度就是7,一个汉字代表三个字符长度,直到遇到/0
所以strlen(“哈h/0hah”),长度就是4,遇到/0结束嘛
int main()
{
    char a[] = "abc";
    
    int m = sizeof(a);
    
    NSLog(@"%d",m);
    
    return 0;
}
putput 4,因为/0,sizeof也给算一个字节。

int main()
{
    
    int m = sizeof('a');
    
    NSLog(@"%d",m);
    
    return 0;
}
output 4,因为sizeof默认常量为int类型,'a'是一个常量,先转化为65,再计算字节数,就是4. 

int main()
{
    char k = 'a';
    
    int m = sizeof(k);
    
    NSLog(@"%d",m);
    
    return 0;
}
现在输出就是1,因为k是一个变量,它有自己的类型



                                                                           第五讲:流程控制与函数


顺序结构:默认的流程结构。按照书写顺序执行每一条语句。

选择结构:对给定的条件进行判断,再根据判断结果来决定执行哪一段代码。

循环结构:在给定条件成立的情况下,反复执行某一段代码。


1.选择结构-if

简单使用

 1  if (表达式)  {语句1;}

2   if(表达式) {语句1; }  else{ 语句2;}

3   if(表达式) {语句1; }  

    elseif(表达式){语句2;}

    elseif(表达式){语句3;}

4   if(表达式语句1;


选择结构-switch

简单使用

switch(数值) { case数值1: break;

case数值2: break;

case数值3: break;

case数值4: break;

 … 

default: break;}


2.循环结构

循环结构-while

简单使用

while(表达式) {循环体}


循环结构-do while

特点:一定会执行一次循环体

do{循环体} while(表达式);


循环结构-for

 for(语句1;条件;语句2)

{循环体}

特点:  语句1:初始化,先执行一次语句1(且只执行一次);条件:判断条件是否成立,成立执行循环体,然后执行语句2,并再次判断条件否成立。判断条件不成立退出for循环。



函数

 任何一个C语言程序都是由一个或者多个程序段(小程序)构成的,每个程序段都有自己的功能,我们一般称这些程序段为函数。所以,你可以说C语言程序是由函数构成的

 

返回值类型  函数名(形式参数列表

{

 函数体

}


函数的参数

形参个数和实参一致;参数的传递是值传递;参数名不能跟函数内的局部变量同名;函数可以没有参数

注意

如果没有写返回值类型,默认是int

如果写了返回值,可以不返回

不能嵌套定义函数

死循环调用,自己调用自己

不能重复定义、可以重复声明


关键字

break

1 switch  :退出整个switch语句

2循环结构  退出整个循环语句(while ,do while,for

3只对最近的循环体有效

continue

 循环结构  结束当前循环体,进入下次循环(while ,do while,for

        2 只对最近的循环体有效


return 

结束当前函数,可以出现在代码任何位置

2返回一个具体值给函数



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值