计算机只能理解0/1语言,可以用电路的开闭来表示
而数学中的或和和等一系列逻辑操作可以用复杂电路来表示
首先得下载visual stdio编译器,在官网上下载社区版,下载完之后
按如下操作
点击创建新项目
点击空项目
点击视图->解决方案资源管理器
在右栏找到源文件,右击鼠标,点添加,再点击新建项,一个文件就被创造
当然在下面有cpp 将cpp改成c就是c语言
#include<stdio.h>//引用头文件 .h相当于头文件head
int main()//相当于代码的入口
{
printf("helloooooooooooooo!");//printf相当于一段更复杂的代码完成,需要靠引用前人给我们写好的代码来进行从屏幕上输出到编译器上显示
//printf是一个基本的代码 相当于输出代码
return 0;//相当于代码的出口
}
每个初识c语言的人都会输入这样一段代码
实际上还可以编一段计算器中加法的运算法则:有两种方法
1.依靠主函数中变量
#include<stdio.h>
int main()
{
int a=0;//定义整型a变量
int b=0;//定义整型b变量
int c=a+b;//定义c的运算法则,注意=不是等于的意思,而是赋值的意思,是将a+b的值赋值给c里面
scanf("%d %d",&a,&b);//scanf相当于c++中的cin,从键盘中输入,当然c也是个整型,&的意思是取地址,相当于scanf函数的固定格式了
//scanf不能有\n转义字符,如果有转义字符就会导致输入时
printf("%d\n",c);
return 0;
}
2.依靠函数
int add(int x,int y)
{
int z=x+y;
return z;
}
#include<stdio.h>
int main()
{
int num1=0;
int num2=0;
int sum=0;
scanf_s("%d %d",&num1,&num2);//对应的是add函数,&num1和&num2对应的是x和
sum=add(num1,num2);
printf("%d\n",sum);
return 0;
}
数据结构分为 字符型char 整型int 短整型short 长整型long 单精度浮点型float 双精度浮点型double,那么c语言有没有字符串类型呢?没有,但是可以用双引号”“代替
那如何知道各种数据类型所占内存的大小呢?
可以用编译器来输出计算:
int main()
{
printf("%d\n",sizeof(int));//整型 4
//sizeof()是链式访问,函数内容,以后介绍,但是先了解int必须加()
//变量可以不加() 例如int a 然后sizeof a
printf("%d\n",sizeof(short));//短整型 2
printf("%d\n",sizeof(long));//长整型 4
printf("%d\n",sizeof(float));//单精度浮点型 4
printf("%d\n",sizeof(char));//字符型 1
printf("%d\n",sizeof(double));//双精度浮点型 8
printf("%d\n",sizeof(long long));//更长的整型 8
//单位是字节,后面将会说到整型和浮点型是如何存储在内存中的
return 0;
}
c语言规定sizeof(long) >= sizeof(int)
这说明各种数据类型向计算机申请的空间是不同的,这些需要记住
还有ASCII码值:这是美国ANSI所建立的标准
记住A是65,a是97,当然定义变量时要加''而不是“”,还要用字符型数据类型来定义
不然打出来的不是ASCII码值,而只是普通数字。
#include<stdio.h>
int main()
{
printf("hehe");//每一条语句用分号结尾
//不论打印出什么,都要用双引号括起来
//如果想打印整型用%d
printf("%d\n,a);
//%c打印字符
printf("%c\n,b);
//%f打印浮点型 - 小数
printf("%f\n,a);
//%p以地址的形式打印,指针部分再说
printf("%p\n,a);
//%x打印16进制
printf("%x\n,a);
return 0;
}
那么为什么出现不同的数据类型?一部分是为了区分字符和整型,另一部分是为了分配合理的内存空间,计算机内存也分为bit byte kb mb gb tb pb,1byte=8bit 1mb=1024byte 1gb=1024mb 1tb=1024gb,为什么是1024,因为计算机使用的是二进制,再我们眼中2^10=1024,二进制有0/1 八进制有0-7 十六进制是0-9 + a-f 八进制没有8,这是一个教训,后面一个求字符串长度的题目会用到这个。
进制中我一直不理解的事情是不论n进制经过各种n的各种次方乘法之后就会变成十进制,进制的权重,我问别人说这是定义,但我没有找到相关定义。
常量和变量
通俗的讲,常量就是不变的量,例如各种ASCII码值,身份证号,血型,而变量就是定义的量,可以人为改变的量,工资,身高,体重等等
变量的定义方式:变量要先定义在使用
int main()
{
char c='a';//a就是ASCII码值中的97
//'a'就是常量
int a=0;//把0赋给a,a是变量,后面可以改变a的值,‘=’是赋值的意思,把后面的值赋给前面的变量
//在c中‘==’才是等于的意思
int b=1;//把1赋给b,b是变量
return 0;
}
变量的作用域和生命周期:作用域通俗解释为作用的范围,变量哪里可以用,哪里就是变量的作用域
全局变量和局部变量如果都有那就看局部变量
变量还分定义方式可以是字母,数字,但是开头要用字母或者,不能是数字,变量的定义也不能是关键词,常见的关键词:if else break continue typedef union int char float static struct signed unsigned等等
int main()
{
{//{}中的代码被称为代码块
int a=1;
}
printf("%d\n",a);//a的值打印不出来,是因为a的作用域在里面的{}里
return 0;
}
介绍一下static static关键字是用来修饰变量和函数的
//变量:局部变量和全局变量
void test()
{
static int a = 1;//若加上static则a不会被销毁 打印出结果变成2,3,4,5,6 static的意思是静态的局部变量
a++;//static修饰局部变量,局部变量的生命周期变长
printf(%d\n",a);//输出结果是五个2
}
int main()
{
int i = 0;
while (i < 5)
{
test();
i++;
}
return 0;
}
//全局变量
int main()
{
//extern-声明外部符号
extern int g_val;//如果add文件 里面的g_val前面是static 就会报错
/*static改变了变量的作用域
让变量只能在自己所在的源文件内部使用
出了源文件就没法再使用了*/
printf("g_val=%d\n", g_val);//打印出来了2020
return 0;
}
//修饰函数
static修饰函数,也是改变了函数的作用域-不准确
static修饰函数改变了函数的链接属性,普通函数具有外部链接属性
如果用static修饰函数,会使函数的外部链接属性变成内部链接属性
int a=1;
int main()
{
printf("%d\n",a);//a在主函数外面定义,相当于整个工程的定义
//此时打印a的值就可以打印出来了
return 0;
}//不熟悉下不要定义全局变量,有可能会搞混
生命周期,例如上述代码的a的作用周期是全局,是永恒的,而上上个代码的生命周期就是大括号,除了大括号,它的生命周期就没了
如果用scanf函数的话,可能会出现下列错误,有两个解决方案,一个是在scanf后加上_s,另一个就是在代码的第一行加上#define _CRT_SECURE_NO_WARNINGS,这是预处理指令,后面来详细说
scanf只能是vs编译器使用 如果是gcc编译器就不行 不具有可移植性 跨平台性,所以在vs编译器上就用上述代码scanf只能是vs编译器使用 如果是gcc编译器就不行 不具有可移植性 跨平台性
按ctrl+f5就可以执行代码了,这是一个执行加法的代码,细心的朋友可能看到两个版本一个是debug版本,一个是release版本,debug是平时写代码用的版本,而release是程序测试人员来找错误的版本,也是优化后的版本,有可能在debug版本能跑起来的代码,经过优化后的版本就会出错,也有debug不能跑的代码,在release版本能跑起来,所以不要觉得你写的代码肯定没错,代码也分为三种错误:
1.编译型错误,例如分号没写,或者分支循环的格式不对,这样编译器跑不起来,是最简单的错误
2.链接型错误,一般是未标识,或者拼写错误,这里可以看到代码下方的错误或警告,是简单的错误
3.运行时错误,一般是你觉得没问题,各种运算,逻辑的错误,要让代码一行一行跑起来找错误,或者断点。断点在VS中按f9从你认为错误的行数开始寻找错误,在断点中右击红点还可以输入条件,当然得是符合原条件的条件,左击红点即可取消断点
f10是逐过程调试,例如循环语句中直接跳过循环,f11是逐语句调试,逐语句调试一般是分号或者一行一行调试
然后接下来说常量,常量有四种:字面常量,const修饰的常量,define修饰的常量,枚举常量
1.字面常量:就是我们日常所说的1,2,3,100
2.const修饰的常量
int main()
{
const int num=0; //num就是被const修饰的常量,但num本质上是变量,所以我们管const修饰的常量叫常变量
num=20;//这里会出现错误,因为被const修饰就不能修改,相当于固定
return 0;
}
3.define修饰的常量
#define max 100
int main()
{
printf("%d\n",max);//这里指定max=100,不能修改,以后不论哪里提到max,max都是100,是不可修改的
//这样写便于写其他变量,可以理解为一个不可修改的全局变量
return 0;
}
4.枚举常量:一一列举,枚举
性别:男 + 女 + 保密,开始的值默认为0-n,枚举常量不能改变,若要将主函数中的male改成100,就会报错,枚举常量不变
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
enum Sex
{
male,//逗号
female,
secret,//都是逗号
//这三个值是枚举常量
};//分号不要忘记,这好像是固定格式
int main()
{
//enum Sex s = female;//也可以写成这种格式
printf("%s\n",male);//默认是0
printf("%s\n", female);//默认是1
printf("%s\n", secret);//默认是2
return 0;
}
数组的基本概念:一组数/元素的集合
数组的定义方式:
int main()
{
int arr1[]={0};
char arr2[4]={'a','b','c','d'};
//[]内有数字说明是有几个元素,如果没有数字,系统就会根据后面输入的元素确定[]内的数字
//所以[]内的数字可以省略
return 0;
}
int main()
{
char arr1[]="abc";
char arr2[]={'a','b','c'};
printf("%d\n",strlen(arr1));
printf("%d\n",strlen(arr2));
return 0;
}
下面距离会说明为什么,这里介绍一个函数,叫strlen是求字符串长度的函数,算的是\0之前的字符串长度,第一个是3,第二个是随机值,为什么?因为第二个找到\0不确定
下面是打印数组内的元素
int main()
{
char arr1[]="abc";
char arr2[]={'a','b','c'};
printf("%s\n",arr1);//打印
printf("%s\n",arr2);
return 0;
}
结果一个是abc,而另一个数组是abc乱码,这里要提到一个概念:转义字符,转变原来的意思
记住其中重要的转义字符:\0, \t, \a, \', \n \xdd \ddd 以及他们所代表的意思
一个\t相当于八个space,\0是字符串结束的标志,\a是电脑蜂鸣的声音,\'是双引号
例如我们之前在printf函数中输入的\n就是一个转义字符,意思是换行,\0是结束的意思,arr1数组中检测到\0就结束打印,打印出abc,而arr2数组没有检测到\0就一直打印,打印出乱码,所以一般用第一个数组类型
还有\178代表的意思是什么如果打印出来,那就是八进制的17,也就是10进制中的15,\xff十六进制数字,转换到十进制数字就是1516+151=255,一个十六进制数字是4个二进制数字,因为2^4=16,也可以理解成最大值相等,从而推断出位数的转换关系
注释:作用有两个,一是便于他人看懂,二是不用的代码直接注释掉,更加方便,在C++中是//,在c中是/**/,不过c的这种注释不支持嵌套,所以一般用//的注释方法,在VS中还有快捷键,一个是工具栏中可以看到注释和取消注释,还有就是键盘上的快捷键 ctrl+k+c
操作符:1.首先是算术操作符,类似+-*/%等是基本的操作符,%是取模的意思,正常情况下,+号被省略,一般我们直接定义int a=3;不会是+3,+3也可以
2.移位操作符:<<和>>是移动二进制序列 例如2是01,写在计算机上存的是补码,正数的原码,反码,补码是相同的,负数的原码变补码是最高位不变,因为最高位是符号位,例如int是4个字节,也就是32个bit位
00000000000000000000000000000010是2的原反补码
如果2>>1是什么意思?也就是把2的二进制序列向右移动一位,也就变成了
00000000000000000000000000000001可以理解为除2,同理<<也就是*2的意思了,是整体右移,而不是单独一个1向右移动
负数也同理
原码-反码-补码
原码到反码符号位不变,其他位按位取反,反码加1得到补码
所以11111111111111111111111111111111 -1 补码
所以11111111111111111111111111111110 -1 反码
所以10000000000000000000000000000001 -1 原码 最高位是符号位
那么为什么要设计出原反补码,这是因为补码可以进行二进制的加法,可以搜搜补码是怎么被编出来的,这是一个数学问题
位操作符:&按位与 ,|按位或, ^按位异或
&的意思是把整数换成二进制序列然后n一下,如果全1则1,有0则0;|的意思是有1为1,全0则0,^的意思是全为1或者全为0则是0,有0有1就是1,可以理解成无进制加法
有几个a和b交换个案例,如果可以增加临时变量,那么如下
int main()
{
int a=3;
int b=5
int tmp=0;//把a和b交换
tmp=a;
a=b;
b=tmp;
return 0;
}
如果不能用临时变量,如下
int main()
{
int a=3;
int b=5;
a=a-b;
b=b+a;
a=b-a;
return 0;
}
int main()
{
int a=3;
int b=5;
a=a^b;
b=a^b;//^满足交换律和结合律,可以用无进制来理解这件事
a=a^b;//这是异或的用法,可以省去一个临时变量
return 0;
}
关系操作符:>=(大于等于),!=(不等于),等于==
逻辑操作符:&&和||这是十进制数字的u和n,同理二进制
?:表达式:(exp1?exp2:exp3):意思是exp1是条件,如果exp1为真,那就是走exp2,如果exp2为假,那就走exp3
条件表达式:(exp1,exp2,exp3,....)最终该表达式的结果是最后一个exp,中间的值也得算,算各种变量的值
操作符:++和--,主要是前置和后置的区别,总的来说前置和后置的区别是b的值变不变化,前置++/--b的值会发生变化,后置b的值就不会发生变化
int main()
{
int a = 10;
int b = a++;//后置++ 先使用其值 后++ b=10 a在++变成11 先使用a,在加加
int b = ++a;//前置++,先++再使用,打印出来的是a是11,b是11
int b = --a;//前置--,a是9,b是9
int b = a--;//后置--,a是9,b是10
printf("a=%d b=%d\n", a, b);
return 0;
}
星号操作符 间接访问操作符(解引用操作符) (类型) 强制类型转换
int main()
{
int a =(int) 3.14;//把3.14强制转换成int类型 从double类型转换成int类型
return 0;
}
auto关键词:
int main()
{
auto int a = 10;//局部变量-自动变量 auto一般省略,在c语言被解释成一个自动存储变量的关键字,也就是申请一块临时的变量内存
return 0;
}
getchar和putchar,getchar字义理解为获得输入的字符,putchar为输出的字符,getchar可以理解为scanf,putchar可以理解为printf
int main()
{
char c = 0;
c = getchar();
putchar(c + 32);
putchar('\n');
return 0;
}//输入大写字母就可以转化为小写字母
函数:维基百科对函数的定义是子程序
在c语言中,函数有两个,分别是自定义函数和库函数
库函数,就是在c语言库中自带的函数,例如printf,scanf,getchar,putchar,sqrt等,都是自带函数,比较复杂,可以在一些网站上看库函数的明确定义和实际使用方法,例如msdn cppreference.com cplusplus,自定义函数是自己写的函数,比如两个值中找到大的哪一个,还有把一列数排序,以及从有序或者无序的数中找出来想要的数等等
很明显自定义函数更加多样
自定义函数更重要
函数有参数 参数分为实际参数和形式参数
实际参数可以是常量,变量,表达式,函数等,但是无论实参是何种类型的量,在进行函数调用时,他们必须有确定的值,以便把这些值传送给形参,形式参数是函数名后的参数,一般只有在函数被调用后才会实例化,也就是分配内存单元,所以被叫做形式参数,形式参数在函数调用完成后就被自动销毁了,形式参数就是一个独立的板块,形式参数被存在栈中,是由下至上以此储存,如果在循环时的变量超出数组的边界就会发生栈满,在函数递归不当也会出现栈溢出的现象,下面再说函数递归的限制条件,电脑怎么储存数据?可以分为硬盘,内存,高速缓存区,寄存器,所拥有的空间逐渐减小,但是速度越来越快,如何进行操作?数据拿到cpu进行计算,计算速度异常快,但是如果数据量太大,就会转移到高速缓存区进行计算,如果满了,就拿到寄存器进行计算,速度很快,但是空间很小,和cpu进行配合,内存有8G
实际参数可以是常量,变量,表达式,函数等,但是无论实参是何种类型的量,在进行函数调用时,他们必须有确定的值,以便把这些值传送给形参,形式参数是函数名后的参数,一般只有在函数被调用后才会实例化,也就是分配内存单元,所以被叫做形式参数,形式参数在函数调用完成后就被自动销毁了,形式参数就是一个独立的板块,形式参数被存在栈中,是由下至上以此储存,如果在循环时的变量超出数组的边界就会发生栈满,在函数递归不当也会出现栈溢出的现象,下面再说函数递归的限制条件,电脑怎么储存数据?可以分为硬盘,内存,高速缓存区,寄存器,所拥有的空间逐渐减小,但是速度越来越快,如何进行操作?数据拿到cpu进行计算,计算速度异常快,但是如果数据量太大,就会转移到高速缓存区进行计算,如果满了,就拿到寄存器进行计算,速度很快,但是空间很小,和cpu进行配合,内存有8G/16G 高速缓存区只有几十mb
int add(int x,int y)//x,y就是形式参数
{
int z=x+y;
return z;
}
#include<stdio.h>
int main()
{
int num1=0;
int num2=0;
int sum=0;
scanf_s("%d %d",&num1,&num2);//对应的是add函数,&num1和&num2对应的是x和
sum=add(num1,num2);//num1,num2就是实际参数
printf("%d\n",sum);
return 0;
}
标签:return,函数,int,乱码,printf,main,变量 From: https://blog.51cto.com/u_16259608/7760115