黑马程序员_第一个C程序

----------------------ASP.Net+Unity开发.Net培训、期待与您交流!----------------------

C的简介

        C语言是由B语言演进而来,在经历了几十年的发展历程中,C仍然处于编程语言排行榜的首位,这不由得显示出C语言在计算机语言中的地位。C是一门面向过程的编程语言,这使得它在程序的结构化设计上显得尤为严格,所以要想掌握C语言还是有相当的难度。C是一门贴近底层的语言,在嵌入式开发中,C能发挥出它无与伦比的优势。C的指针可以访问物理地址的内存空间,同时,C的标准库又封装了一些底层功能的实现,使得在底层的开发中,屏蔽了一些寄存器的原始操作,并将其转化成了对便量对数组等一些基本结构类型的简单算法操作。这使得我们在程序的设计上可以更多的考虑逻辑和算法上的实现,而不必设计复杂繁琐的寄存器累加。

C的第一个程序

hello.c的源码如下

#include <stdio.h>

int main()
{
          printf("hello world");
          return 0;
}

         这是我们学习C语言是第一次写的程序,虽然写了千遍万遍,但是还是会有写错的时候。因为在开发中写的代码好多好多,一不留神谁都有把最简单的代码写错或写少的时候。例如:

printf('hello world');//将双引号写成单引号
prinft("hello world"); //咋一看挺对printf

        这些小错谁都偶尔会犯过将它及时的修正过来这是我们程序员的重要工作,所以调试代码也是衡量一个程序员的标准。  

C的背后

        C语言的程序写好之后如果不经过处理的话,它只是一个不起眼的文本文件,没有任何作用。在C程序的背后需要对程序进行处理后生成可以执行的文件,这才是我们需要的程序。C程序的编译过程分四步:预处理,编译,汇编,链接。

       1.预处理(Preprocessing)

      写好的C程序中会有以#开头的标识如#include ,#define,#if,#undef等等,C语言在编译之前就要对这些以#号开头的标识进行预处理工作。因此,所谓的预处理就是对C源程序中的这些以#号开头的预处理指令先进行处理。预处理后一般会生成一个.i文件。如下:

extern char *ctermid (char *__s) __attribute__ ((__nothrow__));
# 906 "/usr/include/stdio.h" 3 4
extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__));



extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__)) ;


extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__));
# 936 "/usr/include/stdio.h" 3 4

# 2 "hello.c" 2

int main()
{
 printf("hello world!");
}

      这是hello.i文件的一部分,预处理后,把原来的C源程序中的头文件全部替换成了实现。预处理后完成了编译前的准备工作。

      

       2.编译    (Compilation)

        编译是程序运行编译时的第一关,主要就是检查语法规范。如果代码没有语法上的错误,符合规范,就会生成对应的汇编代码。代码如下:

	.file	"hello.c"
	.section	.rodata
.LC0:
	.string	"hello world!"
	.text
.globl main
	.type	main, @function
main:
	pushl	%ebp
	movl	%esp, %ebp
	andl	$-16, %esp
	subl	$16, %esp
	movl	$.LC0, %eax
	movl	%eax, (%esp)
	call	printf
	leave
	ret
	.size	main, .-main
	.ident	"GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
	.section	.note.GNU-stack,"",@progbits

       熟悉汇编的人一定对这样的代码不陌生,因为我原来做arm的所以用的是linux环境,生成的汇编代码不是经典的x86汇编。但是arm汇编和在学校学习的汇编都是相通的mov传送对应movl,call跳转都是和x86汇编相通的所以熟悉的人好好看看吧。(这里涉及到一些linux的东西大家有兴趣的还是查资料吧,我也只是明白代码并不知道底层的含义)


      3.汇编    (Assembly)

        汇编就是将已编译好的文件生成对应的二进制文件,但是这个二进制文件并不是可执行的。因为它有关键的一步。

 

      截了一个图因为乱码太多看不懂也不会敲。这就是生成的二进制文件是不是一点规律都没有。


      4.链接    (Linking)

        最关键的一步链接,它是生成可以执行的文件的最后一步。将生成的二进制文件与库进行链接生成最终可执行文件。一般链接是与标准的函数库libc.so.6相链接。但是这样和编译环境,系统,编译器的不同有差异。

 

      总之还是一堆乱码,最后还是建议大家直接写cc hello.c吧,直接生成可执行文件多方便。(如果有想深入研究的建议还是好好看看编译原理吧)

C的printf与scanf

      1.printf

        printf函数,C语言中的输出函数,基本上可以输出任何我们想要输出的东西。输出方法如下:

#include <stdio.h>

int main()
{
	int a = 10;
	char c = 'a';
	float f = 1.6;
	double d = 0.5123456789;
	char *name = "lsmseed";
	long l = 302210123;

	printf("a = %d\n",a);       //%d 以整数形式输出变量a
	printf("c = %c\n",c);       //%c 以字符形式输出变量c
	printf("f = %f\n",f);       //%f 以浮点数形式输出变量f
	printf("d = %lf\n",d);      //%lf 就当和%f一样吧 默认是没有区别的 硬要说的话就是双精度的
	printf("a = %x\n",a);       //%x 以十六进制形式输出变量a
	printf("a = %o\n",a);       //%o 以八进制形式输出变量a
	printf("name = %s\n",name); //%s 以字符串形式输出name
	printf("long = %ld\n",l);   //%ld 以长整形输出变量l
}

           输出结果如下:

                              a = 10
                              c = a
                              f = 1.600000
                              d = 0.512346
                              a = a
                              a = 12
                              name = lsmseed
                              long = 302210123

       这样的输出结果就不用多解释了吧,主要就是一些固定的输出样式,printf还有一种输出就是转义字符的输出,例如程序中的'\n',这样的带反斜杠的字符在printf函数中输出有所不同,举例代码如下

#include <stdio.h>

int main()
{
	char *name = "lsmseed";
	char *num  = "123";
	printf("name = %s num = %s\n",name,num);  // \n是换行 这里仅理解为换行   
	printf("name = %s\tnum = %s\n",name,num); // \t是制表符输出的时候看到的空行多一些
	printf("\0\n");                           // \0就是字符串的结束标识符
	printf("<a>\\\n</a>");                           // \\ 就是输出\ 这个东西是转义\
	printf("\65\n");                          // \65 就是以\ 后面八进制形式输出对应的字符
	printf("\"lsmseed(\'123\')\"\n");         // \" \‘ 就是将",'转义成要输出的与printf中的"相区别
}

       输出结果:

                      name = lsmseed num = 123
                      name = lsmseed    num = 123
                       \
                      5
                      "lsmseed('123')"
       结果很明显,好好的利用转义字符能使我们的程序输出形态有规律,同时也要注意与printf函数本身的区别。

      

      2.scanf  

        scnaf函数,C语言中的读入函数。这个函数经常用来读入我们输入的变量,这个函数将我们的一般输入存入我们想要的变量中与计算机交互。 代码如下:

int main()
{
	int a;
	int b;
	char c;
	long l;
	char *name;
	char *num;
	float f;
	double d;

	printf("inmput a char c:\n");             
	scanf("%c",&c);                      //以字符型读入变量c中
	printf("c = %c\n",c);

	printf("inmput a int a:\n");
	scanf("%d",&a);                      //以整型读入变量a中
	printf("a = %d\n",a);


	printf("inmput int a int b:\n");
	scanf("%d %d",&a,&b);                //以整型读入变量a,b中,中间可输入空格或者回车
	printf("a = %d b = %d\n",a,b);


	printf("inmput a long int l:\n");
	scanf("%ld",&l);                     //以长整型读入变量l中
	printf("l = %ld\n",l);

	printf("inmput a string name:\n");
	scanf("%s",name);                    //以字符串读入指针name中
	printf("name = %s\n",name);

	printf("inmput a float f:\n");
	scanf("%f",&f);                      //以浮点型读入变量f中
	printf("f = %f\n",f);


	printf("inmput a double d:\n");
	scanf("%lf",&d);                     //以双精度浮点型读入变量d中
	printf("double = %lf\n",d);

	return 0;
}

        程序的演示结果如下:

inmput a char c:
c
c = c
inmput a int a:
10
a = 10
inmput int a int b:
20
3
a = 20 b = 3
inmput a long int l:
2343252
l = 2343252
inmput a string name:
lsmseed
name = lsmseed
inmput a float f:
6.6
f = 6.600000
inmput a double d:
7.5
double = 7.500000

       有的环境下演示可能出问题所以可以注释几句再运行,因为scanf是一次读入缓冲区中的数据,所以如果多输入少输入,演示出的结果都有可能与上面不相同。

C的关键字与标示符    

1.关键字

       C语言的关键字是C特有的,用于程序书写和控制程序流程。C标准关键字有32个如下:

auto :声明自动变量

break:跳出当前循环

case:开关语句分支

char :声明字符型变量或函数返回值类型

const :声明只读变量

continue:结束当前循环,开始下一轮循环

default:开关语句中的“其它”分支

do :循环语句的循环体

double :声明双精度浮点型变量或函数返回值类型

else :条件语句否定分支(与 if 连用)

enum :声明枚举类型

extern:声明变量或函数是在其它文件或本文件的其他位置定义

float:声明浮点型变量或函数返回值类型

for:一种循环语句

goto:无条件跳转语句

if:条件语句

int: 声明整型变量或函数

long :声明长整型变量或函数返回值类型

register:声明寄存器变量

return :子程序返回语句(可以带参数,也可不带参数)

short :声明短整型变量或函数

signed:声明有符号类型变量或函数

sizeof:计算数据类型或变量长度(即所占字节数)

static :声明静态变量

struct:声明结构体类型

switch :用于开关语句

typedef:用以给数据类型取别名

unsigned:声明无符号类型变量或函数

union:声明共用体类型

void :声明函数无返回值或无参数,声明无类型指针

volatile:说明变量在程序执行中可被隐含地改变

while :循环语句的循环条件

2.标识符

        C语言的标识符分三种:关键字,预定义标识符和用户自定义标识符。C语言中标识符由下划线,字母和数字组成。标识符只能有下划线和字母开头,不能以数字为标识符的首字母。其中关键字不能用作用户的标识符,用户的标识符使用最好避开与关键字和预处理标识符相似的字符。例如:

关键字if     ----------------------------   标识符 If

关键字int   ----------------------------   标识符 Int

      虽然C区分大小写但是不提倡这样定义标识符。 

3.注释

          C语言中的注释有两种,一种是单行注释//,一种是多行注释/*   */。注释的作用就是对代码的作用进行人为的说明,有时也可以当作调试代码作用的工具。

#include <stdio.h>

int main()
{
        printf("******************\n");
        //printf("lsmseed\n");                   //单行注释
        printf("******************\n");
        /*for(int i = 0; i < 10; i++)
        {
               printf("lsmseed ww\n");           //多行注释
        }*/
}

C的想法(自己的想法

          C语言看上去是古老的语言,其实还是很难学通的,我在工作中看到过很多研究C的工程师,他们当中虽然都做过几年开发,但是很少有把C用的精通的。代码学了一阵都能看懂,但是为什么这样写,怎样写更好都是大难题。因为在实际工作中做C的总会要和硬件打交道的,这时代码写得快还是慢都不是重要的问题,而在于系统在调试的过程中,你怎样迅速发现并解决问题成了最重要的能力。这时代码不仅要熟练,还要与实际的硬件动作相结合,考虑功耗,效率,甚至经费问题。所以,C这门语言应该是一种长期磨练的功夫。


----------------------ASP.Net+Unity开发.Net培训、期待与您交流!----------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值