C语言易错点一

目录

一、关于运算符的总结(简单)

二、代码逻辑的区别

三、关于指针的运算

四、关于c99上面的数组指示器

五、指针数组数组指针的例题

六、关于数据声明代表的意思

七、关于进制数的典型例题

 一、关于运算符的总结(简单)

例题:

int main() {
	int x = 2 , y, z;
	x *= (y = z = 5); printf("%d\n", x);//等于号在14级,自右像左结合,所以z=5,y=5,x=10;
	z = 3;                            //x=10,y=5,z=3;
	x == (y = z); printf("%d\n", x);//此时y=3,z=3,x=10;x的值不会变
	x = (y == z); printf("%d\n", x);// 此时y=3,z=3,x=1;y和z相等为真,此时x的值变为了true,也就为1
	x = (y & z); printf("%d\n", x);//此时x=3,y=3,z=3
	x = (y && z); printf("%d\n", x);//此时x=1,y=3,z=3
	y = 4; 
	x = (y | z); printf("%d\n", x);//此时x=7,y=4,z=3
	x = (y || z); printf("%d\n", x);//此时x=1,y=4,z=3
	printf("%d\n", y);
	printf("%d\n", z);
}

运行结果:

10
10
1
3
1
7
1
4
3

D:\c程序\p2-1\Debug\p2-1.exe (进程 7668)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

二、代码逻辑的区别 

例题(查看两端代码的区别):

第一段代码、

int main() {
	int a, x;
	for (a = 0, x = 0; a <= 1 && !x++;a++) {//!和++的优先级相同,所以从右至左看结合方向,先算++,后算!
		a++;         //a=0->1->2     x=0->1
	}
	printf("%d%d\n", a, x);//a=2,x=1;
}

运行结果:

21

D:\c程序\p2-1\Debug\p2-1.exe (进程 1844)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

第二段代码、

int main() {
	int a, x;
//先进行后置++,但由于后置++是先用x的值在++,所以第一次执行代码时!x为真,然后x++为1
	for (a = 0, x = 0; a <= 1 && !x++; ) {
		a++;          //a=0->1     x=0->1->2
	}
	printf("%d%d\n", a, x);  //a=1,x=2;
}

运行结果:

12

D:\c程序\p2-1\Debug\p2-1.exe (进程 7356)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

三、关于指针的运算  

例题:

int main() {
	int arr[] = { 6,7,8,9,10 };
	int* ptr = arr;
	*(ptr++) += 123;
	printf("%d,%d\n", *ptr, *(++ptr));
	return 0;
}

运行结果:

8,8

D:\c程序\p2-1\Debug\p2-1.exe (进程 5596)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

在这段代码的执行过程中,可能会疑惑为什么打印出来的值为8,我们将代码走一遍,首先ptr指向元素首地址,然后进行*(ptr++)+=123;在这个语句中,因为ptr++是后置++,所以ptr首先进行加等123,此时首元素的值变为129,然后ptr在像后移动一位,此时ptr指向位置的值变为7,但是结果为什么又会变成8呢,这和printf函数入栈出栈顺序有关,printf入栈是从右向左入栈,所以在输出*ptr, *(++ptr)的值的时候,*(++ptr)先入栈,*ptr在入栈。而*(++ptr)此时ptr先像后面移动一位之后,指向了元素8,入栈之后,*ptr在入栈,此时*ptr所解引用的值就为8。最后再出栈,出栈首先*ptr先出栈,然后*(++ptr)在出栈。下面我们将这段话的意思用画图来看一下:

为了更加了解函数的出栈入栈,我们观察一下它们的地址,代码如下:

void Stack_test(int a, int b, int c) {
	printf("a=%d,&a=%x\n", a, &a);
	printf("b=%d,&b=%x\n", b, &b);
	printf("c=%d,&c=%x\n", c, &c);
}
int main() {
	int a = 1, b = 2, c = 3;
	Stack_test(a, b, c);
}

结果如下:

a=1,&a=affb54
b=2,&b=affb58
c=3,&c=affb5c

D:\c程序\p2-1\Debug\p2-1.exe (进程 17388)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

我们知道栈是从高地址像低地址进行开辟,所以看他们的地址我们可以知道是c先入的栈。

 四、关于c99上面的数组指示器

#include<stdio.h>
int main() {// 数组指示器只有在.c文件中才可以使用
	int arr[10] = { 0,0,2,0,0,5,0,0,8,0 };
	
    int brr[10] = { [2] = 2,[5] = 5,[8] = 8 };//剩余没有赋值的默认为0
	
    int err[] = { [2] = 2,[5] = 5,[8] = 8 };  // 数组指示器的最大值就是数组的长度
	
    int hrr[10] = { 1,2,3,[4] = 4,6,[8] = 8 };
    //输出结果为1,2,3,0,4,6,0,0,8,0,这里的6存放在5号下标处
	
    int lrr[] = { 5,1,9,[0] = 1,3,7,[2 * 7] = 6,7,8,[2] = 3 };
	//这时数组长度为17,因为最大下标14的后面还跟了7,8,所以这两个数放在15号和16号下标
	
    for (int i = 0; i < sizeof(lrr) / sizeof(lrr[0]); i++) {  //打印出lrr
		printf("%d", lrr[i]);
	}
}

运行结果:

13300000000000678
D:\c程序\p2-1\Debug\p2-1.exe (进程 16040)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

关于lrr的流程:

519->13700000000000678->13300000000000678

五、指针数组数组指针的例题 

求下面数组的大小:

int main()
{
int arr[3];      //3*4=12

int *a[3];       //指针数组 3*4=12,落脚点在数组,表示存放指针的数组

int** aa[3][4];   //3*4*4=48

int*** aaa[3][4][5];   //3*4*5*4=240

int(*brr)[4];   //数组指针  4,落脚点在指针,指针指向这个数组

printf("%d\n",sizeof(arr));
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(aa));
printf("%d\n",sizeof(aaa));
printf("%d\n",sizeof(brr));

}

运行结果:

12
12
48
240
4

D:\c程序\p2-1\Debug\p2-1.exe (进程 15024)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

六、关于数据声明代表的意思 

1.下面数据声明分别代表什么意思?

float (**def)[10];    //def是一个二级指针,指向一个一维数组的指针,数组元素都是float

double *(*gh)[10]; //gh是一个一级指针,指向一个一维数组,这个数组的元素都是double*

double (*f[10])();//f是数组,有10个元素,每一个元素都是函数指针,指向的函数类型都是没                              //有参数且返回值是double的函数

int *((*b)[10]);  //b是一个一级指针,指向一个一维数组,且数组中元素都是int*

int (*fun)(int); //fun是一个函数指针,指向的函数只有一个int型参数且返回值也是int的函数

int (*(*F)(int,int))(int) //F是一个函数指针,这个函数指针是有两个int型的参数,

//且返回值类型还是函数指针,这个返回值的函数指针指向有一个int参数且返回int的返回值

2.补充说明:

函数指针的应用:

int Max(int a, int b)
{
	return a > b ? a : b;
}
int main() {
	int a = 20;
	int b = 10;
	int(*p)(int, int) = Max;//函数指针,也可以写成 &Max
	int res=p(a, b);
	printf("%d", res);
}

运行结果:

20
D:\c程序\p2-1\Debug\p2-1.exe (进程 7124)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

七、关于进制数的典型例题 

1.13*16=244  在几进制下为真

//在7进制下为真,我们验证一下,在7进制下,13为7+3=10,16为7+6*7^0=13,244为2*7^2+4*7^1+4*7^0=130,最后变为:10*13=130;  

2.15*5=101    在几进制下为真

//同理:15在8进制下为13,5在8进制下为5,101在8进制下为65,最后:13*5=65;成立

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淡蓝色的经典

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值