c语言问题在线解答,?c语言什么意思
大家好,今天来为大家分享c语言问题在线解答的一些知识点,和?c语言什么意思的问题解析,大家要是都明白,那么可以忽略,如果不太清楚的话可以看看本篇文章,相信很大概率可以解决您的问题,接下来我们就一起来看看吧!
C语言问题 在线等
这个表达式的求值顺序为从右到左:
首先计算a/a的值为1,然后计算下一部分赋值语句,也就是a+=1,a的值变成5+1也就是6;下一步是a*=6,a自乘一次变成36;接下来计算a-=36,于是a=a-36,结果为0。
测试如图,环境为Windows XP SP3+ MinGW(gcc4.3),以及ubuntu9.04(Linux 2.6)gcc4.3
实际上如图所示,gcc在-Wall开关下会提示a的这种赋值可能是未定义的行为,因而可能不同的编译器实现会有不同的结果。也就是说,尽管ANSI C99标准中规定了表达式求值的顺序是从右到左,但是并没有规定在一个表达式中一个变量出现多次时,这个变量的值在计算过程中是不是会变。
上面给出的gcc的实现方式是对a随时求值并赋值,然而另一个编译器可能会这样做:(首先咱们通俗的说一下^_^)
我们记住了a的值是5,然后开始从右到左计算:a/a值是1;接下来计算a+=1,根据我们的记忆,a的值是5,于是这部分的值就是6;同样,计算a*=6时,根据我们的记忆,a的值是5,所以结果变成30;然后a-=30,便计算出5-30也就是-25的结果。
这一种理解方式可能跟我们看到的表达式不同,毕竟我们见到的表达式中是随时赋值,而编译器理解成a-=(a*(a+(a/a)))并不是我们想说的计算,——正因为这个原因,大部分编译器实现时都采用的是第一种理解方式,也就是说,尽管C99中没有明确规定,但是大家已经比较统一的采用了第一种也是比较自然的理解方式来编译这段代码。
存在第二种理解方式的原因在于,我们的变量是在内存中的,然而参与计算时大部分数据位于CPU的寄存器中。因而,如果我以这样一种方式去实现运算和优化,即将我们认为经常用到的数据存储在寄存器中,以便提高速度,就会变成这种情况。可能的运行过程如下:
编译器发现a在语句中多次出现,于是将a的值直接mov到某个寄存器中,比如EBX,然后开始计算:a/a也就是EBX/EBX(甚至这句没有而直接就是1),将结果1放在EAX中,然后下一步把EBX加到EAX上,就是那个a+=什么什么,然后再把EBX乘到EAX上,结果仍在EAX,最后EBX-EAX赋值给EAX,再将EAX mov到变量a,就得到了-25这样的结果。
当然,上面仅仅是通过分析得到的可能的运行过程,鉴于大部分编译器都不是这样实现的,而且我这里只有gcc环境,没有办法进行测试,因而我们只能说可能存在,但没有实例。
另外需要提醒楼主,所有牵扯到“未定义”(Undefined)行为的语句都是应该在编程中避免的,因为这些语句将依赖于您特定的编译环境。像上面的语句,如果我想要说明白,并且避免未定义行为,就将该拆开的赋值拆开成多个语句,写成这样:
int a=5;
a+=a/a;
a*=a;
a-=a;
也就是尽量保持语句的简单,一个语句中最多一个赋值。(KISS原则)
呵呵,没想到我速度不够快,楼主又增加了几个题目。看到这些我才想起来,这应该是某些测试题上面的东西了吧?很多测试题甚至包括二级考试的题目都会考察一些与编译器实现和特定环境相关的问题,而如果你不是要学习编译原理这种课程,那么这样的考察是没有任何意义的。很多这样的练习题都是,不会对个人的编程能力有任何提升,反倒使得大家经常钻入“未定义”的陷阱出不来。个人观点是,如果想学好编程,自己动手实践是最好的途径。很多东西可以通过实践去学习,比如您编程发现i++没问题但是1++会报错,于是您就知道了哦原来自增运算只能施加于左值(l-value)……当然一些基础的内容还是必要的。实际上后面这几个题目都很基础,这样的问题应该在学习C语言的前期就能够自己解答的。
废话说的不少,本来我看到第一个题目后只是想说明“未定义”行为的一些东西,所以就稀里哗啦写了这么多。但现在看看您下面的问题我觉得您可能只是想要答案而已,——于是我就顺便把其他题目也答了吧,虽然我的建议是您最好自己去发现,通过教材、实践。
第一个:未定义行为,大多数情况下会是0,具体原因前面说的比较清楚了。
第二个:再纠正一个观点,就是这种不确定的问题并不是机器或者系统的问题,而在于编译器的实现。比如我在32位机器上装32位系统,而运行16位的TC,或者64位机器装32位系统,运行16位程序TC,甚至64位机器装64位系统,运行16位TC,最终由TC编译出来的程序一定是被16位TC限定的只能使用寄存器中的AH, AL, AX, BX...而不能使用EAX, EBX,更不用提RAX(当然RAX们只有64位系统和64为程序才用得到),因而设计编译器时只能自然使用AX大小的变量,也就是16位,于是TC中的int长度为16比特或者说两个字节。我想说明的是这些不确定的问题都是编译器实现时造成的,跟系统无关。
好的言归正传,题目要求“值”所占的字节数,语句就是sizeof(a+4.5),然后您可以通过printf将这个结果输出,当然这个结果在大多数32位编译器上应该是8,因为a是整数,但是4.5是双精度浮点数,运算将默认对整数进行类型转换,变成同样的double型后和4.5进行运算。得到的结果当然也是double型,——而几乎所有32位编译器实现中,double型占8个字节。
这里不得不提到的是C99标准的一个可能会造成众多C程序员疑惑的地方,就是浮点数在程序中默认是双精度的,除非强加f标志表示float型。于是,我们可以测试,如果在前面的语句中将4.5这个数字后面加上f标志成为4.5f,那么结果可能是不一样的。事实上,大部分编译器将float规定为4字节,这样经过类型提升后,4字节的int变成4字节的float,和4字节的float运算,得到的仍然是4字节的float,于是就会得到结果为4。
好的我们继续,第三题是基础知识,很明显的C语言中的运算符有左结合与右结合之分,因而A是错误的,故选A。这个就不多说了。
第四题:关于自增和自减,我们从这个运算符的名字就能够看出,它们是针对一个东西的,而且这个东西要可以改变才行。专业一点儿就是,自增和自减运算仅施加于左值,所谓左值通俗讲就是可以放在等号左边的东西(比如变量,但不是全部变量都可以)另外有一种理解是可以在数据段定位(Locate)内存地址的东西,详细点就是可以被赋值的变量,非“只读变量”。或者就是我们通常所说的变量。(注意变量可以用const进行只读修饰。)
给出答案:单目运算符,只能作用在左值上(或者可以说变量,不过不确切),不能作用在右值(两个空就可以填成常量和表达式,但是注意这也是不确切的)。
这个问题很难给出一个确切的答案,——这也是好多这种题目的共同特征,个人感觉没有必要确切到什么地步,只要能理解就行。而C语言中很多标准的地方都是有争议的,比如左值右值的问题。这些在实际编程中真的都不造成影响,但是有些人就愿意把带有这种色彩的不确定性用来考试……
满意请采纳。
C语言编程问题!!高手救命,在线等答案
分析过程:
重新定义结构体:
typedef struct student{
float c;
float java;
} STU;
然后在for循环内仅使用:
scanf("%f",&stu[i].c);//或者&(stu[i].c)
scanf("%f",&stu[i].java);//或者&(stu[i].java)
问题依旧。
但如果此时已经定义了float fTmp;并在循环体内这样写:
scanf("%f",&fTmp);
stu[i].c= fTmp;
scanf("%f",&fTmp);
stu[i].java= fTmp;
则问题得到解决。
几经修改,最后改成最原先的代码,问题也不存在了,无语……
原因分析:
可能是C运行库的问题,代码方面理论上没有任何问题的。
另外,对于应该输入float的时候用户输入char导致跳过某些变量输入的情况,这和scanf内部实现的机制有关,因为它是靠类型指针来获取对应值的,那么如果对于普通类型(比如float,VC6中为4字节)变量,如果用户的录入有问题(比如char*),scanf会直接跳过当前变量的赋值。针对这种情况,如果非要用C语言而不是C++的话,那么目前还没有好的防止错误或者在输入错误时给出提示的方法。
以下是模拟错误的执行过程:
姓名:张三
C分数:12
JAVA分数:12
姓名:王
C分数:99
JAVA分数:66
姓名:刘
C分数:34
JAVA分数:56
姓名:陈
C分数:aa
JAVA分数:姓名:cc
C分数:bb
JAVA分数:
<01> [0x0013FEE4] 12.00 [0x0013FEE8] 12.00"张三"
<02> [0x0013FF04] 99.00 [0x0013FF08] 66.00"王"
<03> [0x0013FF24] 34.00 [0x0013FF28] 56.00"刘"
<04> [0x0013FF44]-107374176.00 [0x0013FF48]-107374176.00"陈"
<05> [0x0013FF64]-107374176.00 [0x0013FF68]-107374176.00"cc"
Press any key to continue
用于模拟该错误的代码如下:
#include"stdio.h"
#define n 5
struct student
{
int num;
float c;
float java;
char name[20];
};
void main()
{
struct student stu[n];
int i;
for(i=0;i<n;++i)
{
stu[i].num=i+1;
printf("姓名:");
fflush(stdin);
gets(stu[i].name);
printf(" C分数:");
scanf("%f",&stu[i].c);
// printf("[0x%08X] size:%3d\n",&(stu[i].c),sizeof(stu[i].c));
printf(" JAVA分数:");
scanf("%f",&(stu[i].java));
}
printf("\n\n");
for(i=0;i<n;++i)
{
printf("<%02d> [0x%08X]%.2f [0x%08X]%.2f\"%s\"\n",stu[i].num,&(stu[i].c),stu[i].c,&(stu[i].java),stu[i].java,stu[i].name);
}
}
C语言在线等答案 求帮忙
1错:++n是先完成自加1再计算,n++是先把n用于计算后在自加1,计算时调用数值不同,最后n值一样。
2错:程序在计算1<=x<=10时是先判断1《=X是否为真,真为1假为0,然后再用1或0与10比较,值是真为1
3: int x=2,y=8;则计算y/=x+5是y=8/(2+5)=8/7取整之后去掉小数部分是1
4:int a=6,b=3,c=5,d;则计算d=a+b>c;后d=6+3>5结果为真d值为1
5:int a=0,b=0,c=0,d;则计算d=++a||++b&&++c中是先做++a,完成后进入表达式值为1因为||运算是最后算,前面++a为1后电脑就直接得出表达式值为1并赋值给d,b和c因为没有运算所以值仍为0:最后d,a,b,c为1 1 0 0;
6:设int a=0,b=0,c=0,d;则计算d=a--&&b--||c--;后,d,a,b,c的值是多少? 0-1 0-1
在这个算式中先计算a--,运算过程是先用0进入表达式在自减1,当0进入a--&&b--后明显前面为假,b--就不运算了,所以a为-1而b为0;||运算前面为假所以还要继续运算后面的C--并且是先用C的0值进入运算后再自减1,从而||运算两边为假,d为0而c进入了运算为-1;
7:两边是等价的,代入(1 0),(1 1),(0 0)三组数一试便知:
8:不等价,一个是强制类型转换,原来可能是别的类型,一个是定义参数类型.
9:i++,sum=sum+i是两个语句,不能进两个语句进表达式三。
10:在32位系统中sizeof(X)就是4个字节。Y==4:
关于本次c语言问题在线解答和?c语言什么意思的问题分享到这里就结束了,如果解决了您的问题,我们非常高兴。