前言
讲解C语言学习的一些基础知识,了解C语言大概有哪些知识点,但每个知识点不做太过详细的讲解
这篇博客旨在先让大家对C语言的知识有一个大概的轮廓,提高学习能力
之后会对每个知识点做出详细的总结与分析
你若盛开,花香自来
scanf报错
的问题,解决办法可以看我的另一篇博客https://blog.csdn.net/Trong_/article/details/123994821#include //这里是预处理命令
int main() //定义一个主函数
{
//在双引号的中间输入Hello world!
printf("Hello world!\n"); //是一个格式输出的库函数,此时实现在控制台打印一个Hello world!
return 0; //函数结束的标志
//函数结束时返回函数值0
}
int
main()作为主函数可以看作一个程序的入口,也可以看作是唯一
的一个入口,注意程序一定是从主函数开始网线执行的,前面的 int 是一个整形类型,在这里说明函数的返回值是一个整型,与 return 0 ; 相对应。void
main(),但这种写法太过于古老,不推荐使用。\n
的作用是换行,是一个转义字符,C语言规定以分号;
作为一条语句的结束。short 短整型
int 整型 (不带有小数)
long 长整型
long long 更长的整型
float 单精度浮点数
double 双精度浮点数
char ch = 'w'; //字符数据类型的使用
int a = 60 ; //整形的使用
douuble b = 66.6; //浮点型的使用
#include
int main()
{
printf("%zu\n", sizeof(char));
printf("%zu\n", sizeof(short));
printf("%zu\n", sizeof(int));
printf("%zu\n", sizeof(long));
printf("%zu\n", sizeof(long long));
printf("%zu\n", sizeof(float));
printf("%zu\n", sizeof(double));
return 0;
}
其实C语言规定:sizeof(iong)>=sizeof()
就可以
上面%zu是用来sizeof()返回的数据类型,类似的
%d用来打印整型
%f打印单精度浮点数
%lf打印双精度浮点数
%c打印字符
%s打印字符串
printf("%d",b); //使用格式
要注意字符串没有对应的数据类型,可以用数组进行存储
int age = 15; //给变量定义及赋值
float weight = 45.5;
char ch = 'w';
#include
int b = 20; //全局变量
int a = 30;
int main()
{
int a = 10; //局部变量
printf("a=%d\n", a);
printf("a=%d\n", b);
return 0; //那么这里在上面已经定义了局部变量a,这里会不会有问题呢?
}
局部优先
;但是为了代码的可观性建议不要将全局和局部变量的名字写成一样的。//写一个代码,计算2个整数的和
#include
int main()
{
int num1 = 0;
int num2 = 0;//初始化
//输入2个整数
scanf("%d %d", &num1, &num2);//sccanf是一个格式输出函数
//求和
int sum = num1 + num2;
//输出
printf("%d\n", sum);
return 0;
}
作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用
的而限定这个名字的可用性的代码范围就是这个名字的作用域。
- 局部变量的作用域是变量所在的局部范围。
- 全局变量的作用域是整个工程。
变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
- 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束,比如4.3中创建的几个变量,从进入主函数生命周期开始,到return 0;后生命周期结束,要清晰的理解开始与结束。
- 全局变量的生命周期是:整个程序的生命周期,当整个程序执行结束后,生命周期才会结束。
printf("%d\n",60);
printf("%f\n",66.6);
printf("%c\n",'w');
printf("%s\n","Hello world!");
#include
#define MAX 100
#define STR "abcdef"
int main()
{
printf("%d\n", MAX);
int a = MAX;
printf("%d\n", a);
printf("%s\n", STR);
return 0;
}
#define是预处理命令,不可以以“ ; ”号结束。
#include
//性别
enum Sex
{
//枚举常量
MALE,
FEMALE,
SECRET
};
int main()
{
enum Color c = MALE;
printf("%d\n", MALE);
printf("%d\n", FEMALE);
printf("%d\n", SECRET);
printf("%d\n",c);
return 0;
}
注:从运行结果我们可以知道,枚举常量的默认是从0开始,依次向下递增1的。
“Hello world!”
串。
注:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。
#include
#include
int main()
{
char arr1[] = "bit";
char arr2[] = { 'b', 'i', 't' };
char arr3[] = { 'b', 'i', 't', '\0' };
int len = strlen("abc");//求字符串长度的一个函数,string length 头文件 string.h
printf("%s\n", arr1);
printf("%s\n", arr2);
printf("%s\n", arr3);
printf("%d\n", strlen(arr1));
printf("%d\n", strlen(arr2));
printf("%d\n", len);
return 0;
}
\0
作为结束标志才可以正确输出,所以正确认识\0作为字符串的结束标志是非常重要的;在求字符串长度时,\0不计入长度,只看\0前面的部分,这里同样要走注意结尾是否\0的存在,否如果没有计算机打印出来的会是一个随机数。转义字符 | 释义 |
---|---|
\? |
在书写连续多个问号时使用,防止他们被解析成三字母词 |
\' |
用于表示字符常量’ |
\“ |
用于表示一个字符串内部的双引号 |
\\ |
用于表示一个反斜杠,防止它被解释为一个转义序列符。 |
\a | 警告字符,蜂鸣 |
\b | 退格符 |
\f | 进纸符 |
\n |
换行 |
\r |
回车 |
\t |
水平制表符 |
\v | 垂直制表符 |
\ddd |
ddd表示1~3个八进制的数字。 如: \130 X |
\xdd |
dd表示2个十六进制数字。 如: \x30 0 |
这里附一段代码及运行结果供大家参考,思考熟悉如何使用这些转义字符
#include
int main()
{
//printf("%s\n", "(are you ok\?\?)");
//(are you ok] 在一些早期的编译器上??)会被解析成]
printf("%c\n", '\'');
printf("abcdef\n");
printf("\"");
printf("%s\n", "abcdef");
printf("abcd\\0ef");
printf("c:\\test\\test.c");
printf("\a"); //你的电脑会响一声,可以实验一下
printf("abc\nd\tef");
printf("%c\n", '\130'); //打印的是转换成十进制数后所对应的字符,可在ASCII码表中查看
printf("%c\n", '\x063');
printf("%d\n", strlen("qwer t"));
printf("%d\n", strlen("c:\test\628\test.c"));//这一句是一道面试题目,大家可以着重理解一下。
return 0; //提示:8不是八进制数哦
}
if(表达式)
{
代码执行部分1
}
else
{
代码执行部分2
}
注意:if()和else后面都没有没有分号,直接写{}
#include
int main()
{
int coding = 0;
printf("你会去敲代码吗?(选择1 or 0):>");
scanf("%d", &coding);
if(coding == 1)
{
prinf("坚持,你会有好offer\n");
}
else
{
printf("放弃,找不到工作\n");
}
return 0
while()
{
代码执行部分
}
//while循环的实例
#include
int main()
{
int line = 0;
while(line<=20000) //当不满足括号中的条件时循环结束
{
line++;
printf("我要继续努力敲代码\n");
}
if(line>20000)
printf("好offer\n");
return 0;
}
#include
//创建一个求和的函数
int Add(int x, int y) //因为我们要计算的是俩个整型的和,所以要创建俩个整型变量进行接收
{
int z = x+y; //函数内部进行计算
return z; //返回计算结果
}
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0;
printf("输入两个操作数:>");
scanf("%d %d", &num1, &num2);
sum = Add(num1, num2); //将要进行计算的俩个参数传给函数
printf("sum = %d\n", sum);
return 0;
}
int arr[10] = {1,2,3,4,5,6,7,8,9,10}; //定义一个整形数组,最多放10个元素
必须是一个常量,不可以是变量
,其内的数值表示这个数组可以存放的元素个数,同时这个数值是可以省略不写的,省略后会根据后面的元素个数自动确定。C99标准之前
,数组的大小都是用常量或者常量表达式来指定;而C99标准之后
,支持了变长数组
,这个时候允许数组的大小是变量,但是这种指定方式的数组是不能初始化
的,VS编译器对C99中的一些语法支持不是很好,是不支持变长数组的。int main()
{
int m = 100;
int arr4[m];//C99标准之后支持但不能进行初始化,在vs编译器中是错误的
return 0;
}
int arr[10] = {0};
//如果数组10个元素,下标的范围是0-9
#include
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;
}
按顺序分别对应着加、减、乘、除、取模(就是取余数);属于双目操作符,对应着俩个操作数,如:a + b
强调一些除法和取模需要注意的点:
1. 除号的两端都是整数的时候,执行的是整数除法,如果两端只要有一个浮点数就执行浮点数的除法
2. 取模操作符的两个操作符只能是整数
-
双目操作符
注意这里这个=可不是等号,它是赋值号,如:int a = 1;是把1赋给变量a;要与等号区分,C语言中的等号用==来表示。关于其他的赋值号大家联系下面这段代码理解,一样的道理。
int main() { int a = 0;//初始化 a = 20;//赋值 a = a + 3;//a=23 a += 3;//这俩个式子是等价的 a -= 3; a = a - 3;//同样也是等价的 return 0; } ``` -
C语言中
0表示假
非0表示真
int flag = 2;//真
if (!flag)//假,不会打印结果
{
printf("hehe\n");
}
int a = -10;
int b = +a;//但在负数前面加一个+号还是负数
printf("%d\n", b);//结果为i0
int a = 10;
printf("%d\n", sizeof(a));//4
printf("%d\n", sizeof(int));//4,当它后面跟数据类型时,()不可以省略
printf("%d\n", sizeof a);//4,后跟变量,()可以省略不写,这也证明了它不是一个函数
int arr[10] = { 0 };
printf("%d\n", sizeof(arr));//40 计算的是整个数组的大小,单位是字节
printf("%d\n", sizeof(arr[0]));//计算数组第一个元素的大小
printf("%d\n", sizeof(arr) / sizeof(arr[0]));//10 - 数组的元素个数
int a = 10;
int b = a++;//后置++,先使用,后++
// b = a; a=a+1;此时先使用a把a赋给b,再对进行自加
//此时b = 10,a = 11
int b = ++a;//前置++,前++,后使用
//先对a进行自加,在使用啊的值赋给b,a=a+1;b=a;
//这里a,b的值都是11
int a = 10;
int b = a--;
//b=a; a=a-1;
int b = --a;
//a = a - 1; b = a;
printf("%d\n", b);// 9
printf("%d\n", a);// 9
int a = (int)3.14;
//int a = int(3.14);错误用法
printf("%d\n", a);//3
//3.14 字面浮点数,编译器默认理解为double类型,吧它强制转换为int类型
&& 逻辑与 - 并且 || 逻辑或 - 或者 int a = 0; int b = 0; if (a && b) { printf("hehe\n"); } int a = 0; int b = 0; if (a || b) { printf("hehe\n"); }
三目操作符,针对三个操作数
当exp1为真时,执行exp2;当exp1为假时,执行exp3
int a = 10; int b = 20; int r = (a > b ? a : b);
逗号表达式
exp1, exp2, exp3, …expN
逗号表达式就是逗号隔开的一串表达式
逗号表达式的特点是:从左向右依次计算,整个表达式的结果是最后一个表达式的结果
int main() { int a = 10; int b = 20; int c = 0; // c=8 a=28 表达式的结果为5 int d = (c=a-2, a=b+c, c-3); printf("%d\n", d); return 0; }
前面俩个我们已经有一些了解,分别用在数组和函数上;后俩个在后面的结构体会介绍到
int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int n = 3; arr[n] = 20;//[]就是下标引用操作符 arr和3就是[]的操作数 //a+b return 0; } //函数调用操作符() int Add(int x, int y) { return x+y; } int main() { int sum = Add(2, 3);//()就是函数调用操作符,Add,2,3都是()的操作数 return 0; }
typedef
.//将unsigned int 重命名为uint_32, 所以uint_32也是一个类型名
typedef unsigned int uint_32;
int main()
{
//观察num1和num2,这两个变量的类型是一样的
unsigned int num1 = 0;
uint_32 num2 = 0;
return 0;
}
typedef struct Node
{
int data;
struct Node* next;
}Node;
int main()
{
//观察n1和n2,这两个变量的类型是一样的
struct Node n1;
Node n2;
return 0;
}
static
.修饰局部变量
.static修饰局部变量的时候,局部变量出了作用域,它不会再被销毁。本质上,static修饰局部> 变量的时候,改变了变量的存储位置,影响了变量的生命周期,生命周期变长,当整个程序执>行结束后,的生命周期才结束。
修饰全局变量
.static修饰全局变量的时候,这个全局变量的外部链接属性就变成了内部链接属性,其他源文件(.c)就不能再使用到这个全局变量了。
修饰函数
.一个函数本来具有外部链接属性的,但是被static修饰的时候,外部链接属性就编程了内部链接属性,其他源文件(.c)就无法使用了。
register
.int main()
{
//寄存器变量
register int num = 3;//建议: 3存放在寄存中,只是建议,不是决定
return 0;
}
宏
//define定义标识符常量
#define NUM 100
int main()
{
printf("%d\n", NUM);
int n = NUM;
printf("%d\n", n);
}
//#define 定义宏
//宏是有参数的
#define ADD(x,y) ((x)+(y))
int main()
{
int a = 10;
int b = 20;
int c = ADD(a, b);
printf("%d\n", c);
return 0;
}
这里在代码部分会穿插讲解这俩个操作符
#include
int main()
{
int num = 10;
#//取出num的地址
//注:这里num的4个字节,每个字节都有地址,取出的是第一个字节的地址(较小的地址)
printf("%p\n", &num);//打印地址,%p是以地址的形式打印
return 0;
}
int num = 10;
int *p;//p为一个整形指针变量
p = #
int main()
{
int a = 10;//向内存申请4个字节,存储10
//&a;//取地址操作符
//printf("%p\n", &a);//0x0012ff40
int* p = &a;
//p就是指针变量
*p = 20;//解引用操作符,意思就是通过p中存放的地址,找到p所指向的对象,*p就是p指向的对象
printf("%d\n", a);//20
//char ch = 'w';
//char * pc = &ch;
return 0;
}
#include
int main()
{
//int* p;
//char* p2;
//不管是什么类型的指针,都是在创建指针变量
//指针变量是用来存放地址的
//指针变量的大小取决于一个地址存放的时候需要大多空间
//32位机器上的地址:32bit位 - 4byte,所以指针变量的大小是4个字节
//64位机器上的地址:64bit位 - 8byte,所以指针变量的大小是8个字节
printf("%zu\n", sizeof(char*));
printf("%zu\n", sizeof(short*));
printf("%zu\n", sizeof(int*));
printf("%zu\n", sizeof(float*));
printf("%zu\n", sizeof(double*));
return 0;
}
//学生(创建一个复杂类型)
struct Stu
{
//成员
char name[20];
int age;
char sex[10];
char tele[12];
};
void print(struct Stu* ps)
{ //通过指针解引用找到对象进行访问
printf("%s %d %s %s\n", (*ps).name, (*ps).age, (*ps).sex, (*ps).tele);
//->
//结构体指针变量->成员名,与上面的效果是一样的
printf("%s %d %s %s\n", ps->name, ps->age, ps->sex, ps->tele);
}
int main()
{
//对一个对象的信息进行描述
struct Stu s = {"zhangsan", 20, "nan", "15596668862"};
//结构体对象.成员名
printf("%s %d %s %s\n", s.name, s.age, s.sex, s.tele);
print(&s);
return 0;
}