C语言的基础知识

  • Post author:
  • Post category:其他



目录


C语言的第一个程序(梦开始的地方)


数据类型


数据类型的大小


变量


变量的命名


局部变量与全局变量


常量


四种常量:


字符串


​编辑


选择语句


if语句


循环语句


while语句


for语句


函数


库函数


自定义函数


数组


数组下标


数组的输出


指针


如何存放指针地址


指针变量有多大?


结构体


输出结构体



C语言

是一门

通用计算机编程语言

,广泛应用于

底层开发

。C语言的设计目标是提供一种能以简易 的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语 言。 尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的 C语言程序可在许多电脑平台上进行编译,甚至包含一些

嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台

。 二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制 定了一套完整的美国国家标准语法,称为

ANSI C

,作为C语言最初的标准。 C语言是一门面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。 其编译器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。


其实上面的内容都不是很重要ovo,主要看下面的

C语言的第一个程序(梦开始的地方)

在程序员的心中,第一个程序都是一个叫做Hello Word的程序

#include <stdio.h>

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

那就很好奇了,为什么大家第一个接触到的程序都是这个呢,带着好奇,本人去搜索了一下,得到了这样的答案:

hello,world 起源

hello world的起源要追溯到1972年,贝尔实验室著名研究员

Brian Kernighan

在撰写“B语言教程与指导(Tutorial Introduction to the Language B)”时初次使用(

程序

),这是目前已知最早的在计算机著作中将hello和world一起使用的记录。之后,在1978年,他在他和

Dennis Ritchie

合作撰写的C语言圣经“

The C Programming Language

”中,延用了“hello,world”句式,作为开篇第一个程序。在这个程序里,输出的”hello,world”全部是小写,没有感叹号,逗号后有一空格。虽然之后几乎没能流传下来这个最初的格式,但从此用hello world向世界打招呼成为惯例。

有趣的是,如果你去看Brian Kernighan的

wiki

页面,他成果列表里的第一条,不是《C程序语言》,不是《UNIX编程环境》,而是看似不起眼的“hello world”。

还读到一句很有意思的话:

Hello World


是简单的,即便没有任何基础,你也可以轻松理解,但它又不是苍白的,它带有一个程序语言鲜明的特色,体现了该语言最基本的思想和特征。同样也是hello world,让人体会到第一份成功的喜悦。

希望学习编程的我们,将这一份成功的喜悦含在嘴中,一直走下去


数据类型

C语言最基本的点,数据类型,就像是一个人出生之后,定义你是男还是女的基本性别一样

数据类型主要是用来决定你的数据所展示出来的类型

char         //字符数据类型(键盘上能打出来的出数字以外的都叫字符)
short        //短整型
int          //整型
long         //长整型
long long    //更长的整型
float        //单精度浮点型
double       //双精度浮点型


Qs:

为什么没有字符串类型?


As:

C语言中,字符串类型是由


char字符数据类型组成的数组


来表示。


数据类型的大小

#include <stdio.h>
int main()
{
    printf("%d\n", sizeof(char));
    printf("%d\n", sizeof(short));
    printf("%d\n", sizeof(int));
    printf("%d\n", sizeof(long));       //虽说int与long大小相同,但默认long大于int
    printf("%d\n", sizeof(long long));
    printf("%d\n", sizeof(float));
    printf("%d\n", sizeof(double));
    printf("%d\n", sizeof(long double));
    return 0;
}

得到:

1    2    4    4    8    4    8    8

此处的大小为byte(字节)

ps:1 bit = 8 byte   1 b = 8 bit   1 kb = 1024 b   1 mb = 1024 kb   1 gb = 1024 mb


变量



变量的命名


变量的命名:

只能由

字母

(包括大写和小写)、

数字



下划线

( _ )组成。


不能以数字开头



长度

不能超过63个字符



变量名中

区分大小写

的。

变量名

不能使用关键字


//定义例子

int age = 150;
float weight = 45.5f;
char ch = 'w';




局部变量与全局变量


#include <stdio.h>
int global = 2019;//全局变量
int main()
{
    int local = 2018;//局部变量
    //下面定义的global会不会有问题?
    int global = 2020;//局部变量
    printf("global = %d\n", global);
    return 0;
}


上面的局部变量global变量的定义其实没有什么问题的!

当局部变量和全局变量同名的时候,局部变量优先使用。

ps:需要注意的是,当在同一文件中引用不同源文件的变量,需要加上extern声明外部符号,例子如下:


常量

四种常量:

1.字面常量(就是字面意思)

2.const修饰的常变量(由变量变化而来)

3.由#define定义的标识符常量

4。枚举常量

//字面常量演示
3.14;    //字面常量
1000;    //字面常量
    
//const 修饰的常变量
const float pai = 3.14f;   //这里的pai是const修饰的常变量
pai = 5.14;                //是不能直接修改的!
//const 修饰的常变量仍具有变量的属性 (变长数组的例子)
    
//#define的标识符常量 演示
#define MAX 100          //define定义的常量最好大写,且最好不加分号
    printf("max = %d\n", MAX);
    
//枚举常量演示
enum Sex
{
 MALE,
 FEMALE,
 SECRET
};
printf("%d\n", MALE);
printf("%d\n", FEMALE);
    printf("%d\n", SECRET);
    //注:枚举常量的默认是从0开始,依次向下递增1的

字符串

这种由

双引号

引起来的一串字符称为

字符串字面值

,或者简称

字符串

注:

字符串的结束标志是一个 \0 的转义字符

。在计算字符串长度的时候 \0 是结束标志,

不算作字符串内容



拓展

:strlen()函数可以计算 \0 之前有多少个元素,这里可以用strlen函数去查看arr1,arr2,arr3三个函数的区别,可以发现,arr2没有加 \0 的情况下,出现了len为35,原因是strlen没有识别到\0,便会一直往下数,printf函数同理,在没有加 \0 的情况下会打印乱码,而arr1是字符串,\0 自动隐藏,arr2在数组中添加了 \0 ,故不会出现像arr2的问题。


选择语句

if语句

当if()括号内表达式满足某一条件是,执行if{}领域内语句

若不满足if()括号内条件,则执行else{}领域内语句

ps:else并非必要存在

#include <stdio.h>
int main()
{
    int coding = 0;                               //定义一个变量coding
    printf("你会去敲代码吗?(选择1 or 0):>");     
    scanf("%d", &coding);                         //输入一个值放入变量coding中
    if(coding == 1)                               //若coding的值为1,执行if括号内语句
   {
       prinf("坚持,你会进入大公司\n");
   }
    else                                          //若coding的值不为1,执行else括号内语句
   {
       printf("放弃,回家种田\n");
   }
    return 0;
}

循环语句

while语句

当while()括号内表达式满足某一个条件时,执行while{}领域内语句

#include <stdio.h>
int main()
{
    printf("学习编程\n");                  
    int line = 0;                           //定义一个变量line并初始化
    while(line<=20000)                      //当变量line<=20000时,执行while括号内语句
   {
        line++;                             //变量line自增1
        printf("我要继续努力敲代码\n");
   }
    if(line>20000)                          //如果line>20000,执行if下的语句
        printf("进入好公司\n");
    return 0;
}

for语句

当for循环与while差不多,区别在与他将判断前,判断,判断后的步骤全部放入括号中,便于查看

int main()
{
    int a = 666;
    for(int i = 0; i<10; i++)    //定义一个i=0,当i小于10时,执行for括号内语句,并且i自增1
    {
        a += 1;
        printf("%d\n",a);
    }
    return 0;
}


>点击此看详细内容<


函数


函数的特点就是简化代码,方便调用

库函数

库函数是

编译器内自带的函数



不需要自己编辑

,但如果想要使用,需要

先调用头文件

,才可使用头文件内部的库函数,例如我想使用printf函数来打印某一数据,就需要在代码最前端引用printf的头文件 stdio.h,方式如下  #include <stdio.h>

ps:库函数查询

:https://cplusplus.com/

自定义函数

自定义函数与库函数不同的是,是由使用者

根据自己的需求而定义

的函数

自定义函数格式:


ret_type


fun_name

(

para1

, * )

{



statement;//语句项


}


ret_type

返回类型


fun_name

函数名


para1

函数参数

#include <stdio.h>

int sum( int x , int y )      //定义一个有两个整型参数x,y 叫做sum的函数,返回值为int,
{
    sum = x + y ;             
    printf(" %d ", sum ) ;
    return sum ;              //返回sum值
}

int main()                    //定义主函数
{
    int a, b ;                //定义两个变量a,b
    scanf("%d %d",&a, &b);    //输入a,b值
    sum(a, b)                 //调用sum函数,并且将变量a,b作为sum函数的参数
    return 0;
}


使用说明:

1.自定义函数的返回值类型(ret_type)如何定义取决于该自定义函数最终返回值的类型,如上sum值返回的是整型,那ret_type就得是int类型

2.自定义函数的参数(para1,*)称为形式参数(形参),而真正放入函数中使用的叫做实际参数(实参),如上自定义自定义函数内x,y为形参,而主函数调用自定义函数传入的a,b为实参

自定义函数会根据传入实参的量去进行运算,并最终返回根据实参计算出的值


拓展:形参与实参的区别


数组

C语言中给了数组的定义:一组相同类型元素的集合

int arr[10] = {1,2,3,4,5,6,7,8,9,10};

定义一个整形数组,最多放10个元素

格式如下:

ret_type  name [length] = {ele1,*}

返回类型  数组名字 [数组长度] = { 数组元素1,*}


注意:

一般而言,数组长度必须是一个常量


,但是在部分编译器上,

支持

变长数组


,可以在数组长度内放变量而不会报错,但不能初始化数组(建议查找或点击链接了解有关变长数组的概念)

数组下标

C语言规定:数组的每个元素都有一个下标,


下标是从0开始的

int arr[10] = {1,2,3,4,5,6,7,8,9,10};

对于这个数组而言,1的下标索引值就是0,2的下标索引值就是1,以此类推

数组还可以通过下标索引值来访问相应元素

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d\n", arr[1]);
}

这里访问数组arr下标索引为1的元素,也就是2,并将其打印

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d\n", arr[1]);
	arr[1] = 666;
	printf("%d\n", arr[1]);
}

还可以通过下标索引修改对应的元素,上面代码将下标索引为1的元素,也就是2修改为666,最终重新输出会输出666

数组的输出

#include <stdio.h>
int main()
{
 int i = 0;
 int arr[10] = {1,2,3,4,5,6,7,8,9,10};
 for(i=0; i<10; i++)
 {
       printf("%d ", arr[i]);
 }
 printf("\n");
    return 0;
}

这里是通过循环遍历数组去打印数组内元素


拓展:循环遍历的总结


指针


内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。所以为了有效的使用内存,就把内存划分成一个个小的内存单元,

每个内存单元的大小是1个字节

。 为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。

QS:内存编号地址是怎么产生的?

AS:电脑具有32位与64位操作系统,可以理解为有32根电线与64根电线,电线通电有高电频与低点频,换作数字信号即为0和1,对于32位电脑来说,若有32根电线,每条电线拥有出现0和1的两种可能性,那么32根电线一共会出现 2^32 种 0和1 的排列方式,也就是会出现2^32个地址(64位则会出现2^64种),每个内存分配一个编号地址,这便是内存编号地址的产生原因。

int main()
{
    int a = 10 ;
    //&a 实际占据了4个字节的空间,每个字节都有地址,但是&a拿到的是第一个字节的地址
}

ps:打印地址的符号为 “

%p

如何存放指针地址

int main()
{
    int a = 10;
    int* pa = &a;
}

内存编号 = 内存地址 = 指针

pa是一个存放地址(指针)的变量,所以把 pa 叫做指针变量,pa 的类型就是int*

QS:如何理解int*

AS:以上面代码为例子,假设变量a的地址为10,那么pa存放的便是a的地址10,



i

nt*中的*是说明pa是指针变量,而int指的是pa指针变量存放的对象a是int类型


(& 取地址操作符)= 来


(* 解引用操作符)= 去



拓展:取地址与解引用的具体内容

int main()
{
	int a = 10;
	int* pa = &a;
	printf("%d\n", a);      //输出a的值
	printf("%d\n", *pa);	//输出a的值(*pa==a)
	printf("%p\n",pa);		//输出a的地址(%p专门打印地址)
	printf("%p", &a);		//输出a的地址(可以通过取地址符&来输出a的地址)
	return 0;
}

从上面代码可以看出各种不同的有关指针的表达方式的相同点

指针变量有多大?

指针变量用来存放地址,地址是32/64位机器上,由32/64个0和1组成的二进制序列,需要32/64bit位的空间存放,指针变量就需要4/8个字节存放


指针变量的大小取决于地址的大小


32位平台下地址是32个bit位(即4个字节)


64位平台下地址是64个bit位(即8个字节)


结构体

c语言提供了结构体

用来描述复杂对象


直接上例子

#include <stdio.h>

struct Student
{
	char name[20];
	int age;
	char id[15];
	float score;
};//分号必须存在
  //以上为声明结构体类型
int main()
{
	struct Student s1 = { "阿强",19,"2022212010",99.5f };//创建结构体对象s1
	struct Student s2 = { "阿珍",19,"2022010212",99.5f };//创建结构体对象s2
	//struct Student s3;
	return 0;
}

通过struct修饰,声明一个结构体类型(结构体包含的元素类型)

再在头函数中创建以该结构体类型为框架的结构体的对象s1,s2

输出结构体

通过

结构体对象 . 成员

的方法输出

printf("%s %d %s %f\n", s1.name, s1.age, s1.id, s1.score);//打印结构体s1的内容
printf("%s %d %s %f\n", s2.name, s2.age, s2.id, s2.score);//打印结构体s2的内容
	

通过

指针结构体解引用 . 成员

的方法输出

加括号的原因是(*ps)需先解引用s1的地址

struct Student * ps = &s1;
printf("%s %d %s %f\n", (*ps).name, (*ps).age, (*ps).id, (*ps).score);//通过结构体指针打印s1内容

通过

指针结构体  —>操作符  成员 的方法输出



拓展:有关 —> 操作符的使用

struct Student * ps = &s1;
printf("%s %d %s %f\n", ps->name, ps->age, ps->id, ps->score);//效果同上,表达方式不同



版权声明:本文为m0_74483774原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。