c 源码,C语言源代码是什么
亲爱的读者们,你是否对c 源码和C语言源代码是什么的相关问题感到困惑?别担心,今天我将为你解答这些问题,让你对此有更清晰的认识。
c语言代码是什么
C语言源代码,就是依据C语言规则所写出的程序代码,常见的存储文件扩展名为.c文件和.h文件,分别对应C源文件(source file)和C头文件(header file)。
C语言是一门编程语言,简单点说,就是由人类书写按照一定规范书写的字符,通过一定手段(编译链接)转换后,可以让电脑或者其它电子芯片"读懂",并按照其要求工作的语言。
在所有的编程语言中,C语言是相对古老而原始的,同时也是在同类语言中更接近硬件,最为高效的编程语言。
C语言是一门面向过程的计算机编程语言,与C++、C#、Java等面向对象编程语言有所不同。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、仅产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
C语言描述问题比汇编语言迅速、工作量小、可读性好、易于调试、修改和移植,而代码质量与汇编语言相当。C语言一般只比汇编语言代码生成的目标程序效率低10%-20%。因此,C语言可以编写系统软件。
当前阶段,在编程领域中,C语言的运用非常之多,它兼顾了高级语言和汇编语言的优点,相较于其它编程语言具有较大优势。计算机系统设计以及应用程序编写是C语言应用的两大领域。同时,C语言的普适较强,在许多计算机操作系统中都能够得到适用,且效率显著。
C语言拥有经过了漫长发展历史的完整的理论体系,在编程语言中具有举足轻重的地位。
c库函数源码
深入printf
/***
*printf.c- print formatted
*
* Copyright(c) 1985-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines printf()- print formatted data
*
*******************************************************************************/
#include
#include
#include
#include
#include
#include
#include
/***
*int printf(format,...)- print formatted data
*
*Purpose:
* Prints formatted data on stdout using the format string to
* format data and getting as many arguments as called for
* Uses temporary buffering to improve efficiency.
* _output does the real work here
*
*Entry:
* char*format- format string to control data format/number of arguments
* followed by list of arguments, number and type controlled by
* format string
*
*Exit:
* returns number of characters printed
*
*Exceptions:
*
*******************************************************************************/
int __cdecl printf(
const char*format,
...
)
/*
* stdout''PRINT'',''F''ormatted
*/
{
va_list arglist;
int buffing;
int retval;
va_start(arglist, format);
_ASSERTE(format!= NULL);//断言宏。如果输出格式字符串指针为空,则在DEBUG版下断言,报告错误。
_lock_str2(1, stdout);
buffing= _stbuf(stdout);//stdout:指定输出到屏幕
retval= _output(stdout,format,arglist);
_ftbuf(buffing, stdout);
_unlock_str2(1, stdout);
return(retval);
}
以上为printf()的源代码
1、从含有可选参数函数中获得可选参数,以及操作这些参数
typedef char*va_list;
void va_start( va_list arg_ptr, prev_param);
type va_arg( va_list arg_ptr, type);
void va_end( va_list arg_ptr);
假定函数含有一个必选参数和多个可选参数,必选参数声明为普通数据类型,且能通过参数名来获得该变量的值。可选参数通过宏va_start、va_arg和va_end(定义在stdarg.h或varargs.h中)来进行操作,即通过设置指向第一个可选参数指针、返回当前参数、在返回参数后重新设置指针来操作所有的可选参数。
va_start:为获取可变数目参数的函数的参数提供一种便捷手段。设置arg_ptr为指向传给函数参数列表中的第一个可选参数的指针,且该参数必须是va_list类型。prev_param是在参数列表中第一个可选参数前的必选参数。
va_arg:返回由arg_ptr所指向的参数的值,且自增指向下一个参数的地址。type为当前参数的类型,用来计算该参数的长度,确定下一个参数的起始位置。它可以在函数中应用多次,直到得到函数的所有参数为止,但必须在宏va_start后面调用。
va_end:在获取所有的参数后,设置指针arg_ptr为NULL。
下面举例说明:
#include
#include
int average( int first,...);
void main( void)
{
/* Call with 3 integers(-1 is used as terminator).*/
printf("Average is:%d\n", average( 2, 3, 4,-1));
/* Call with 4 integers.*/
printf("Average is:%d\n", average( 5, 7, 9, 11,-1));
/* Call with just-1 terminator.*/
printf("Average is:%d\n", average(-1));
}
int average( int first,...)
{
int count= 0, sum= 0, i= first;
va_list marker;
va_start( marker, first);/* Initialize variable arguments.*/
while( i!=-1)
{
sum+= i;
count++;
i= va_arg( marker, int);
}
va_end( marker);/* Reset variable arguments.*/
return( sum?(sum/ count): 0);
}
返回值为:
Average is: 3
Average is: 8
Average is: 0
综上所述,在printf()函数中,可以只输出一个字符串,也可按照一定的形式输出含有多个可选参数的字符串信息。因此,首先就要通过这些宏来获取所有的可选参数。在上面的源码可以看出printf()中,只使用了宏at_start,将可选参数的首地址赋给了arglist。
2、锁定字符串及输出字符串到屏幕
#define _lock_str2(i,s) _lock_file2(i,s)
void __cdecl _lock_file2(int, void*);
#define _unlock_str2(i,s) _unlock_file2(i,s)
void __cdecl _unlock_file2(int, void*);
int __cdecl _stbuf(FILE*);
void __cdecl _ftbuf(int, FILE*);
int __cdecl _output(FILE*, const char*, va_list);
在output函数中,读取格式字符串中的每一个字符,然后对其进行处理,处理方式根据每一个字符所代表的意义来进行,如:普通字符直接利用函数WRITE_CHAR(ch,&charsout);输出到控制台。
其中的主要部分是对转换说明符(d,c,s,f)的处理,现在将对其中的部分代码进行详细说明,这里只说明最基本的转换说明符,对这些须基本的转换说明符进行修饰的修饰符,程序中单独进行处理。下面是函数output()(output.c)部分源代码:
case ST_TYPE:
//表示当前处理的字符的类型为转换说明符。
...
switch(ch){
//下面对参数的获取都是利用宏va_arg( va_list arg_ptr, type);来进行的。
case''c'':{
//从参数表中获取单个字符,输出到缓冲字符串中,此时,type=int
buffer[0]=(char) get_int_arg(&argptr);/* get char to print*/
text= buffer;
textlen= 1;/* print just a single character*/
}
break;
case''s'':{
//从参数表中获取字符串,输出到缓冲字符串中,此时,type=char*
int i;
char*p;/* temps*/
text= get_ptr_arg(&argptr);
...
}
break;
case''w'':{
//对宽字符进行处理
...
}/* case''w''*/
break;
...
case''e'':
case''f'':
case''g'':{
//对浮点数进行操作
...
#if!LONGDOUBLE_IS_DOUBLE
/* do the conversion*/
if(flags& FL_LONGDOUBLE){
_cldcvt((LONGDOUBLE*)argptr, text, ch, precision, capexp);
va_arg(argptr, LONGDOUBLE);
//对长双精度型进行处理,此时,type=long double
}
else
#endif/*!LONGDOUBLE_IS_DOUBLE*/
{
//对双精度型进行处理,此时,type=double
_cfltcvt((DOUBLE*)argptr, text, ch, precision, capexp);
va_arg(argptr, DOUBLE);
}
...
break;
//对整型变量处理
case''d'':
case''i'':
...
goto COMMON_INT;
case''u'':
radix= 10;
goto COMMON_INT;
case''p'':
...
goto COMMON_INT;
case''o'':
...
注:对于浮点型double和long double,有相应的转换说明符(%f表示双精度型,%lf表示长双精度型),而float却没有。其中的原因是,在K&RC下,float值用于表达式或用作参数前,会自动转换成double类型。而ANSI C一般不会自动把float转换成double。有些程序已假定其中的float参数会被转换成double,为了保护大量这样的程序,所有printf()函数的float参数还是被自动转换成double型。因此,在K&RC或ANSI C下,都无需用特定的转换说明符来显示float型。
综上所述,转换说明符必须与待打印字符的类型。通常,用户有种选择。例如,如要打印一个int类型的值。则只可以使用%d,%x或%o。所有这些说明符都表示要打印一个int类型的值;它们只不过提供了一个数值的几种不同表示。类似一,可以用%f、%g和%e来表示double类型的值。但如果转换说明与类型不匹配,将会出现意想不到的结果。为什么呢?问题就在于C向函数传递信息的方式。
这个失败的根本细节与具体实现相关。它决定了系统中的参数以何方式传递。函数调用如下:
float n1;
double n2;
long n3;
long n4;
...
printf("%ld,%ld,%ld,%ld",n1,n2,n3,n4);
这个调用告诉计算机,要把变量n1,n2,n3和n4的值交给计算机,它把这些变量放进称作栈(stack)的内存区域中,来完成这一任务。计算机把这些值放进栈中,其根据是变量的类型而不是转换说明符,比如n1,把8个字节放入栈中(float被转换成double),类似地,为n2放了8字节,其后给n3和n4各放了4个字节。接着,控制的对象转移到printf();此函数从栈中读数,不过在这一过程中,它是在转换说明符的指导下,读取数值的。说明符%ld指定printf()应读4个字节(va_arg( va_list arg_ptr, type)中type=long),因此printf()读入栈中的4个字节,作为它的第一个值。但是这只是n1的前半部分,这个值被看成一个long整数。下一个说明符%ld读入4个字节,这正是n1的后半部分,这个值被看成第二个long整数。类似地,第三、第四次又读入n2的前后两部分。因此,尽管我们对n3和n4使用了正确的说明符,printf()仍然会产生错误。
C语言源代码是什么
数字版“拼图”游戏C源代码:
#include<time.h>
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<windows.h>
int i, j, r, k;//i、j、r用于循环, k存放随机数值
int m, n;// m、n是当前空位的下标, t标记排序是否成功
int a[4][4];//存储4×4共16个数字的数组
void show(void);//输出数组表格
void csh(void);//初始化界面
int yes(void);//判断排序是否成功
void up(void);//数字向上移动到空位(空位则下移)
void down(void);//数字向下移
void left(void);//数字向左移
void rght(void);//数字向右移
void inkey(void);//按键操作
void gtxy(int x, int y);//控制光标移动的函数
int main(void)
{ while(1)
{csh();
while(1)
{ inkey();
show();
if( yes())
{gtxy(6,12); printf("你成功了!再来一局y/n?"); break;}
}
if(getch()==ʹnʹ)break;
}
return 0;
}
void csh(void)
{r=0;
CONSOLE_CURSOR_INFO cursor_info={1,0};//以下两行是隐藏光标的设置
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
for(i=0;i<4;i++)//给数组a依序赋值
for(j=0;j<4;j++)
{ if(i==3&& j==3) a[i][j]=0;
else a[i][j]=1+r++;
}
a[3][3]=a[1][1]; a[1][1]=0;//把a[3][3]与a[1][1]的值交换一下
m=1; n=1;
srand((unsigned)time(0));//初始化随机数发生器
for(r=0;r<500;r++)//将数组各值打乱
{k=rand()%(4);//取0-3随机数,分别代表上下左右四个方向
switch(k)
{ case 0:{ up();break;}
case 1:{down();break;}
case 2:{left();break;}
case 3:{rght(); break;}
}
}
printf("\n\n\t\t数字拼图");
printf("\n\t┌──────┬──────┬──────┬──────┐");
printf("\n\t│││││");
printf("\n\t├──────┼──────┼──────┼──────┤");
printf("\n\t│││││");
printf("\n\t├──────┼──────┼──────┼──────┤");
printf("\n\t│││││");
printf("\n\t├──────┼──────┼──────┼──────┤");
printf("\n\t│││││");
printf("\n\t└──────┴──────┴──────┴──────┘");
show();
}
void show(void)
{for(i=0;i<4;i++)
for(j=0;j<4;j++)//gtxy(7*j+9, 2*i+4)是光标到指定位置输出数字
{gtxy(7*j+9,2*i+4); if(a[i][j]==0)printf("│");
else if(a[i][j]>9)printf("%d│",a[i][j]);
else printf("%d│",a[i][j]);
}
}
void inkey(void)
{ int key;
key=getch();
switch(key)
{ case 72:{ up(); break;}
case 80:{down(); break;}
case 75:{left(); break;}
case 77:{rght();break;}
}
}
void up(void)
{ if(m!=3)//移动时要考虑空位"0"是否已经在边界
{ a[m][n]=a[m+1][n]; m++; a[m][n]=0;}
}
void down(void)
{ if(m!=0)
{a[m][n]=a[m-1][n]; m--; a[m][n]=0;}
}
void left(void)
{ if(n!=3)
{ a[m][n]=a[m][n+1]; n++; a[m][n]=0;}
}
void rght(void)
{ if(n!=0)
{ a[m][n]=a[m][n-1]; n--; a[m][n]=0;}
}
int yes(void)
{ r=0;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{ if(a[i][j]!=1+r++) return(r==16)?1:0;}
}
void gtxy(int x, int y)//控制光标移动的函数
{ COORD coord;
coord.X= x;
coord.Y= y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
END,本文到此结束,如果可以帮助到大家,还望关注本站哦!