百度问问有以下程序: main(int argc,char int*argv[ ]) { int n=0,i; for( i=1; i<argc;i++) n=n*10+*argv[i]

在循环语句中,for(i=0;i&n;i++)和for(i=0;i&n;++i)有什么区别?
我同学有简单地告诉我,i++的话要先copy出一个i然后赋值,用原来的i继续其他运算,最后再把copy出来的i做个increment,然后返还给原来的i。而++i直接在原来的i上做increment。结论:当n很大的时候,++i速度比i++快。比如语法上a = i++; 是等号右边的变量赋值给左边的变量,但是赋值应发生在所有运算之后。这就比较矛盾,如果用上诉理论就能解释得清楚。请问他说的对吗?
按时间排序
这个问题把我们送回了80年代那个勒紧裤腰带开发程序的日子,多两三条代码程序会慢到死吗,我相信现在已经不是主要问题了,就算出现问题,那也是编译器作者的问题,不是程序员的问题。
只是人的习惯问题,就好比为什么每个语言第一个程序叫hello world而不是hello monkey
告诉你同学:“你想错了”,或许你能赚一顿饭?我们看看不加优化情况下,gcc编译出来的结果:C源代码如下 - int main(int argn, char *argv[])
int sum, i;
for (i = 0; i & 100; i++)
for (i = 0; i & 100; ++i)
对应的汇编代码如下
0x080483ed &+0&: push
0x080483ee &+1&: mov
0x &+3&: sub
$0x10,%esp
0x &+6&: movl
$0x0,-0x8(%ebp)
0x080483fa &+13&: movl
$0x0,-0x4(%ebp)
# 第一次循环开始
0x &+20&: jmp
0x804840d &main+32&
0x &+22&: mov
-0x4(%ebp),%eax
0x &+25&: add
%eax,-0x8(%ebp)
# sum += i
0x &+28&: addl
$0x1,-0x4(%ebp)
0x0804840d &+32&: cmpl
$0x63,-0x4(%ebp)
# 判断i&100
0x &+36&: jle
0x8048403 &main+22&
# 条件跳转
0x &+38&: movl
$0x0,-0x4(%ebp)
# 第二次循环开始
0x0804841a &+45&: jmp
0x8048426 &main+57&
0x0804841c &+47&: mov
-0x4(%ebp),%eax
0x0804841f &+50&: add
%eax,-0x8(%ebp)
# sum += i
0x &+53&: addl
$0x1,-0x4(%ebp)
0x &+57&: cmpl
$0x63,-0x4(%ebp)
0x0804842a &+61&: jle
0x804841c &main+47&
0x0804842c &+63&: mov
0x &+68&: leave
0x &+69&: ret
So,i++和++i在这里没有任何区别。就单独的表达式i++和++i而言,从开发编译器的角度来看,确实存在差别。但是编译器的开发者也会顺手抹去毫无意义的代码(我们可以认为是内置的最基本优化,无需开关控制的部分),结果就完全相同了。
加一段timer不就知道了么,我只记得老师说不管是++i还是i++都比i=i+1快,i++在n十分大的时候慢于++i,原理早忘了(或许应该查看下汇编)
经过简单测试发现差别不大#include &iostream&
using namespace std;
int main()
int n=100000;
for(int a=0;a&n;a++){
for(int a=0;a&n;a++){
学校里就讲到++i先将i加一再运算,i++把原值运算后再加一,好low,突然感觉。。。。。。
在C++里,假如i是int,那么没有任何不同,无论开不开优化,你没有使用自增后的i值,编译器根本就不会“复制”一个i。如果i是个自定义类型,又自定义了前缀和后缀++操作符,那自然是不一样的。
本来,这样的问题我不会回答,心里说“编译器君掩面不语”后跳到下一个问题。但是冲着你的第一句话:“(这个问题估计1万个程序员也不到1个能真正领悟)”。我忍不住进来跟你说,同学,你一定要成为一个万里挑一的程序员啊。
我想说的是现在已经是2015年了,编译器都发展了几十年了连这点优化都做不到也好意思拿得出来?程序优化的重点应该放在项目的性能瓶颈上,而不是抠这种几乎无意义的细枝末节。再说了,如果你非觉得编译器不可信非要写成++i,那我可以告诉你把for(int i=0; i&n; ++i)
写成for(int i=n-1; i&=0; --i)
会更快(汇编可以少一个CMP指令,当然主流的编译器基本都会自动帮你做这样的优化)你会把程序中所有循环改成下面那种吗?
按C来说i++把i增加1,返回i增加前的值至于是先计算整个表达式还是先增加i应该是未定义的++i先把i加1,返回i的引用在for里i++和++i由于返回值没有被使用,因此会被优化成一样的结果
不开优化,并没有什么不同开启优化,编译器是不会在这种地方拖慢你的程序的能把循环内的乘法优化成两个add指令,循环本身的跳转也大大简化能把循环内的乘法优化成两个add指令,循环本身的跳转也大大简化优化之后的代码已经看不到所谓的i++和++i了(哪位聚聚能给解释一下那两个add指令是如何变成乘法的)有些人就是不肯平心静气地和人说话,是吧
i++返回的是i本身的值,++i返回的是i+1的值,可以写一个小程序测试一下就知道了。
for循环中不好说明,不妨假设有这样一个表达式:
int i = 3;k = ++i;
//#1k = i++;
//#2前置递增运算符:对象递增加一再使用即: /*
*/i = i+1;
//i的值为4k =
//k 的值为4后置递增运算符:创建一个临时对象,将临时对象替换调用原变量的位置,原变量+1即:/*
*/k = int(i);
//int(i) 是一个临时对象,值为4i = i+1;
//i 的值为5也就是说后置递增相比前置递增会创建一个临时对象int(i),使用临时对象赋值给k,所以后置递增会比前置递增慢那么一丢丢。
习惯用++i,但我相信编译器对此的优化,不会在意它的性能。对于a = i++;那段,我不大清楚你的问题,不知道下面这样说能不能帮你理解。你说的“等号右边的变量赋值给左边的变量”,那既然是“值”,这个值也就可以来自于另外一个变量(假设是t),t保存了i自增前的值,然后把t返回给了左边进行赋值操作。把++理解成下面这个方法。int jiajia(int &i)
a = i++;就变成了a = jiajia(i);
如果 i 是系统类型,两者没有性能区别。绝大多数编译器可以生成同效率代码。由于所谓的多余复制的变量并没有被用到(i++的返回值无人使用),所以编译器优化之后跟++i等价。两者性能区别理论上存在于当 i 是一个自定义的类,并且这个类重载了++操作符,并且这个类重载「后增量」操作符时使用了值复制作为返回值的情况,在这种情况下,有时编译器能优化掉多余的复制,有时不能。所以++对于自定义对象类型来说会有题主所说的情况。
所有支持++的语言中,按定义++i的速度一定大于等于i++
在循环语句中,for(i=0;i&n;i++)和for(i=0;i&n;++i)有什么区别?没。我同学有简单地告诉我,i++的话要先copy出一个i然后赋值,用原来的i继续其他运算,最后再把copy出来的i做个increment,然后返还给原来的i。而++i直接在原来的i上做increment。无依据的臆测。比如语法上a = i++; 是等号右边的变量赋值给左边的变量,但是赋值应发生在所有运算之后。错。====================================做点正事,不要问没有意义的问题。现代程序设计不怎么追求速度,通常认为代码可读性优先于程序效率。即使要求效率也是从算法和数据结构入手,从for语句中挖掘速度无异于从牙缝里找吃的希望吃的更饱些。
一:i++ 和 ++i从Java的角度来说,这两个没有区别。(证据,生成的字节码一样。)从C/C++的角度来说,++i可能更好一些,因为不用存储一个中间变量。(但我怀疑这个是可以被编译器优化掉的。)二:运算顺序讨论一个语句中如,i = i++ + i++。究竟++操作是何时发生的,对于C/C++语言可能没有意义,因为是未定义行为,对于Java来说是有意义,因为Java明确定义了运算顺序。
已有帐号?
社交帐号登录
无法登录?
社交帐号登录C语言问题.动态分配部分._百度知道
C语言问题.动态分配部分.
程序输入 并保存至 100 度超 80 字符字符行 读 完所 输入先输其度 超 40 字符 行输 其行 考虑面两种实现 式 :1 )用两维字符数组保存字符行;2 )用字符指针数组字符行保存通态配存储块我用第二种式 #include &stdio.h&
#include &stdlib.h&
#include &string.h&
int main(int argc, char* argv[])
char *p[100];
int i=0,n=0;
p[0]=(char*)malloc(81*sizeof(char));
while(scanf(&%s&,p[i])!=EOF){
p[i]=(char*)malloc(81*sizeof(char));
for(n=0;n&=i;n++){
if(strlen(p[n])&40&&strlen(p[n])!=0)
←问题行现&&右侧条件我测试通随意想能现问题貌似空行看起没啊
printf(&%s\n&,p[n]);
for(n=0;n&=i;n++){
if(strlen(p[n])&40)
printf(&%s\n&,p[n]);
提问者采纳
#include &stdio.h&#include &stdlib.h&#include &string.h&int main(int argc, char* argv[]){ char *p[100]; int i=-1,n=0; do {
p[i]=(char*)malloc(81*sizeof(char)); }while(scanf(&%s&, p[i])!=NULL);
for(n=0;n&i;n++) {
if(strlen(p[n])& 40)
//←问题行现&&右侧条件我测试通随意想能现问题貌似空行
//看起没啊
printf(&%s\n&,p[n]);
} for(n=0;n&i;n++) {
if(strlen(p[n])&=40)
printf(&%s\n&,p[n]);
return 0;}没问题 for循环控制候n&i输入i++配址 输入结束符 所i代表址没实际数据用着输
提问者评价
来自团队:
其他类似问题
#include &stdio.h&#include &stdlib.h&#include &string.h&int main(int argc, char *argv[]) {
char *p[100];
int i = 0,n = 0;
p[0] = (char *)malloc(81*sizeof(char));
while(scanf(&%s&,p[i]) != EOF) {
p[i] = (char *)malloc(81*sizeof(char));
for(i = 0;i &n++) {
if(strlen(p[i])&40&&strlen(p[i]) !=0 )
printf(&%s\n&,p[i]);
for(i = 0;i &i++) {
if(strlen(p[i]) & 40)
printf(&%s\n&,p[i]);
system(&PAUSE&);
return 0;}
为您推荐:
动态分配的相关知识
其他1条回答
标准输入面打车
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁main(int argc,char*argv[]) { int i,len=0; for(i=1;i&i+=2) len+=strlen(argv[i]); Printf(&%d\n&,_百度知道
main(int argc,char*argv[]) { int i,len=0; for(i=1;i&i+=2) len+=strlen(argv[i]); Printf(&%d\n&,
argc是命令行总的参数个数
argv[]是argc个参数,其中第0个参数是程序的全名,以后的参数命令行后面跟的用户输入的参数,比如:
main(int argc,
char* argv[])
for (i = 0; i& i++)
cout&&argv[i]&&
执行时敲入
F:\MYDOCU~1\TEMPCODE\D1\DEBUG\D1.EXE
输出如下:
F:\MYDOCU~1\TEMPCODE\D1\DEBUG\D1.EXE
--------------------------------------------------------------------char
*argv[]是一个字符数组,其大小是int
argc,主要用于命令行参数
参数,数组里每个元素代表一个参数;比如你输入
&t.c&--------------------------------------------------------------------------------------------
有了这个思路问题不难解决了吧楼上回答很对,加上我的帮你理解
其他类似问题
为您推荐:
直接运行输0输命令行参数加入执行程序a.exe运行式:a.exe mm输2假运行式a.exe mm nnn则输5说程序统计命令行参数参数1始所字符串度并输
strlen的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁

我要回帖

更多关于 int argc 的文章

 

随机推荐