简单来说什么是C语言,就是用c写的语言就是C语言。接下来言归正传。
1.没有注意数据类型存储范围
int main(int argc, char **argv)
{
char a;
a = 1;
for (a=0; a<128; a++)
printf("#");
return 0;
}
你猜是循坏了128,还是死循环呢? 答案是死循环,因为a的类型是有符号char型,它的取值范围为-128-127;当a=127时,a<128,会继续执行,代码执行完之后a会加1,但是a的最大值为127,在加1就会变成最小值-128,为什么会变成-128呢,就是我们平时的时钟,时间为12:59时,再过一分钟就会变成1点,这就简单的说明了为最大值加一会变成最小值,最小值减1就会变成最大值。在计算中数据都是以2进制进行存储的,127在计算机存储时为0x7f,加1,就会变成0x80,因为char中0x80表示最小值-128;所以-128小于128,以此类推,a<128;永远为真。
2.打印类型时,选择正确的格式。
例如 double a = 4.5;
printf("%lf",a);
一定不能使用%f打印,否则会报警告
小结:只要时double ,long类型的数据打印时别忘了加上l
3.显示无符号整数
%u:显示无符号整数
%o:显示无符号八进制
%x:显示无符号16进制
4.各种数据类型的变量与0进行比较正确的书写方式
int a=5;
if (0 == a);
char ch = 'a';
if ('\0' == char)
float f =0.152;
if ((x>-0.000 001) && (x<0.000 001))
bool flag = 1;
if ( flag )
int *p = &a;
if ( NULL == p)
5.转义字符:转移字符是一种特殊的字符常量,转移字符常以反斜线"\"开头
常用的转移字符:
\a:蜂鸣,响铃
\b:回退:向后退一格
\f:换页
\n:换行:光标到下行行首
\r:回车,光标到本行行首
\t:水平制表符
6.调试代码有很多中一般分为printf调试,bug调试等、
我要讲的是用printf调试,这种方式方便简单易操作。
利用FILE,LINE,FUNCTION,DATE,
TIME实现代码跟中
FILE:显示代码的文件名;
FUNCTION:显示调用函数的名称,没有默认为主函数
LINE:显示所在的行数;
TIME:显示时间
DATE:显示日期
7.数据类型的转换
在多种数据类型混合运算时,系统一般自动完成类型转换
转化的规则:存储长度较短的转化成存储长度较长的,并且不丢失
(a)自动转换 :
int a=5; double d = 4.5;
a + d ;结果是double类型的
(b)赋值转换
int a=5; double d = 4.5; char ch;
ch = a + d ;结果是char类型的
(c)强制转换
a = (int ) d + c;
字符型数据赋值给整型变量时,将字符数据放到整型变量存储单元的低八位中
--对于无符号类型,则将字符的8位放到整型变量低八位中,高24位补零
--对于有符号字符类型,若最高位为0,整型变量高24为补0,若字符最高位为1 ,则高24位补1
char 0000 0001 --> 0000 0000 0000 0000 0000 0001
1111 1111 --> 11111 1111 1111 1111 1111 1111
将一个整型数据赋值给一个char类型变量时,直接将其低八位原封不动的送到char型变量(即截断),精度会丢失。
将整型数据赋给浮点型变量时,数值不变,但以浮点型形式存放到变量中精度可能丢失;
将浮点型数据赋给整型数据,直接将浮点型数据存放到int类型存储空间中;
将浮点型赋给double类型数据,直接将30--22位放到double类型62--52中,其他的放到剩下51位中,
将double类型数据赋给float类型,直接将取7位有效数字放到浮点型存储空间中。
8.运算符
运算符是非常常见的,无论你用那种语言写编程都会用到运算符,谈到运算符,就会想到他的优先级,这里我们不讲他的优先级,直降容易出错的地方。
优先级:不是谁的优先级高就先算谁,所谓的优先级就是结合型,谁的优先级高就和谁结合,至于知怎算个的要根据优先级运算顺序,相同的优先级运算顺序时由编译器决定的
(a) ++、 --
a++:就是献给状态值a;然后自行加一
++a; 先自加一,再给a+1的状态结果;
-- a ; a++ 同理
(b) 不要对同一个变量,在一个表达式多次赋值
例如: a = 5;
c = a++ + a++ + a++; //编译器不知道从那边开始算
a = 5;
a = a++;同理
printf("%d %d %d %d %d\n", a++, a++, a++, a++, a++);
你要想这么做,就把a++ 结果赋值给其他变量,用其他变量进行计算
(c) 位移(只能用于整数或者字符型)
无符号数据类型:右移时左边高位补0;左移时右边补0;
有符号:正数:右移时,左边补0;左移时右边补0;
负数:右移时,左边补1;左移时,右边补0
对于正数右移一位相当于除以2,左移1位相当于乘以2;
(d)逻辑运算符
& | ^
& :两者都是1,才为1,否则位0; 功能置零
| :两者只有要一个为1,结果为1,否则为0, 功能置一
^ : 相同为假,不同为假, 功能取反
举例: & A & 1 = A ; A & 0 = 0
| A | 1 = 1; A | 0 = A;
^ A ^ 1 = ~A ; A ^ 0 = A;
(e) 条件运算符:三目运算符
表达式1 ? 表达式2 : 表达式3
条件运算符运算有先后顺序的:先算表达式1,若表达式1为真,算表达式2,结束,否则,计算表达式3,算完结束
例题: a = b=c= 1;
x = a++ ? b++ ?c--:c++:b--?c++:c--;
结果为:a=2;b=2,c=1;
(f)逗号运算符
优先级最低,将两个表达式链接起来,从左往右以此计算、
注意:并不是任何地方的出现的逗号都是逗号运算符,例如函数参数,也是用逗号来间隔的
9.scanf和printf函数:
scanf:
修饰符 功能
m :输ru数据宽度,遇到空格或不可转换字符结束
* :抑制符,指定输入项读入后不赋给变量
输入分割符的指定:
一般以空格、TAB或回车键作为分隔符
其他字符作分割符:格式串中两个格式符间字符
例题:scanf("%d,%d,%d",&a,&b,&c);
输入方式必须以:12,13,14回车
scanf("%d ",&a);
输入 12 12回车才能结束否则不结束 过滤分割符,要输入两次
scanf("a=%d",&a);
输入:必须以“a=”开头+数字+回车 结束
scanf("%*4d",&a);
输入:132345 a=45;
scanf("%d%c",&a,&c);
输入 12回车 就结束了 因为%c会自动读取回车、空隔
char ch;
int i;
for (i=0; i<10; i++)
{
printf("i=%d\n",i);
scanf("%c",&ch);
printf("%c\n",ch);
getchar(); //表示取走回车键,只能取走一次
}
%s he %c 遇到空格,回车键就自动停止
scanf("%[^\n]",&a);//表示不取空格键
scanf("%[a-z]",&a);//表示只取a-z
10.switch:
是一种多路判断语句,他判断表达式置是否与整型或字符常量例表中的某个值相匹配,若找到了相应的匹配,就会执行与常量关联的语句,switch,case,和default都是关键字。语句可以时简单或符合语句。
switch后面只需要用圆括号括起来,而且switch的主题用{}括起来,计算表达式的数据类型与指定case常量数据类型匹配
switch后的表达式可以包含任何变量名,也可以时常量
case后面只能时常量(整型和字符型)
case后面长量不能为相同,可以不按照顺序,不影响程序结果,但是一般时按照顺序。
case 后面不加break,则表示找到匹配之后往下执行,如果没有遇到break;会执行到程序结束,
default:是说明没有匹配的选项进行说明,放到开始位置要加上break,否则会继续执行,放到末尾,就不用加了,执行玩后就结束了
例如:case 5: 语句 ;break;
case 5: 语句;break; //错误,有两个相同的case,因为在匹配中不知道该选则那个,
case 1: 语句 ;break;
case 7 || 6: 语句;break; //错误7 || 6 返回状态结果为1,与case 1:重复 ,但是你可以这样写 case 6: case 7: 语句;break;
last :一维数组和二位数组
讲数组,就要集合,什么集合,就是把相同的东西放在一起。对于数组呢?也是一样的,就是把相同的类型的数据放在一起,如果不用一个数组来存放相同数据,用变量来表示,就会显得杂乱无章,没有条例性,时间久了,只有上帝知道,你所定义变量的含义了;接下来正式介绍数组
《存储类型》 《数据类型》 变量名 [元素个数] //数组实际是由 元素数据类型+[元素个数]组成
存储类型:说白了就是你定义了变量存放的位置。(一般默认auto,放在栈中,当代码块执行结束就是放空间,static 为静态类型,放在静态取,用static定义数据存储类型,知道程序结束才释放空间,否则不释放空间,extern声明为全局变量,可以使用其他文件用extern声明的变量,作用范围用于整个函数,register修饰符暗示编译程序相应的变量将频繁的使用,如果可能话应将放在CPU寄存器中,以加快其存储速度)
int a[5]; //a实际可以看成 int [5] ;类型
//数组的大小在编译的时候确定,而变量在运行时才有值
//数组元素个数必须为整型或char类型
初始化:定义同时对变量或数组元素赋值
int a[3] = {1,2,3}; //全部初始化.
char ch[5] = {65,66,67}; //没有初始化的部分自动清0
int be[100] = { [95] =15,} ; //指定元素初始化,没有初始化的部分自动清零
int c[6];
c[2] = 2; //对元素赋值,不会影响其他元素,不对数组初始化,起内存的存放的值是未知的,不对数组进行越界检查,对于越界的元素访问可能造成不可预知的错误;
int cat[9];
cat[2] = 5; //[ ] 数组定义固定格式
2[cat] = 5; //引用变量时,[ ] 时变址运算符 a[i] == (a+i) == (i+a) == i[a];
数组名的含义:
#define N 10
int a[N];
1.代表整个数组:只有子啊&a,和sizeof(a)
&a得到的是整个数组地址
sizeof(a)得到整个数组的字节大小
2.其他情况数组名代表第一个元素的地址 即 a + 0 == &a[0], sizeof(a+0); 代表第一个数组元素的地址,是一个地址常量,不可以自加,不可以对数组名进行赋值
a++; //错误
a = {1,23,5};//错误
int a[0]; 表示是一个地址,不能存放数据
3.数组遍历
int a[10]= {0};
int i;
for (i=0; i<10; i++)
{
printf("%d\n",a[i]);
}
4.int a[4] ;//数组在编译时,空间就已经确定了,变量在执行的时候才申请空间赋值
二维数组:其实是由一维数组组成的,内存存储空间时线性。
int a[] [5]; //可以省略一维数组的下标;
初始化:
int a[5][5]= {15,6,3,9,7,8,2,1,5,4,6};//部分初始化,其他都清0;
int c[8][9] = { [6][3]=9,};指定元素初始化,先定行,再指定行中的某一个
二维数组名的含义:
1.数组名:
sizeof(数组名) ==>整个数组大小
&(数组名) ==> 整个数组地址
2.对于二维数组来说。每一个元素都是一个一维数组,数组名中放在第一个一维数组地址&a[0] ,除了上面的情况,都是代表了&a[0] 即 a == &a[0];
int a[M][N];
例如: sizeof(a) == 4*M*N;
sizeof(a[0]) == 4*N;
sizeof(a[0][0]) == 4;
遍历:
#define M 4
#define N 5
int main(int argc,char **argv)
{
int a[M][N]={0};
int i,j;
for (i=0; i<M; i++)
{
for (j=0; j<N; j++)
printf("%d\t",a[i][j]);
printf("\n");
}
return 0;
}
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。