华为笔试的一道题,看似简单

时间:2022-04-30 14:36:33
在windows下,写出运行结果,说明为什么?
1,
int arr[]={6,7,8,9,10};

int *ptr=arr;

*(ptr++)+=123;

printf("line11%d,%d",*ptr,*(++ptr));

printf("line22%d,%d",*ptr,*(ptr++));

2,
int arr[]={6,7,8,9,10};

int *ptr=arr;

*(ptr++)=*(ptr++)+123;

printf("%d,%d",*ptr,*(++ptr));

43 个解决方案

#1


up

#2


我没有实际上机试,只是根据自己的理解猜的。

第1题:
line11 8,8
line22 9,8
因为调用printf的时候是从右向左压栈,因此先计算后面的表达式。

第二题:
9,9

#3


楼上分析完全正确!

#4


up

#5


因为调用printf的时候是从右向左压栈,因此先计算后面的表达式。

这句话要记住

#6


因为调用printf的时候是从右向左压栈,因此先计算后面的表达式。
这句话要记住
---------
哦,记住了

#7


不过我的输出是:
第1题:
line11 8,8
line22 8,8

#8


但输出结果是line118,8  line228,8真奇怪.谁能解释一下吗?
第二题为9,9.

#9


第一题的正确结果应该是
line11 8,8
line22 8,8

#10


line 8,8 输出后*ptr就是指向8
在第二个printf时候,ptr++是在整个printf以后才计算的,所以都是8

#11


谢谢~  受益fei浅~

#12


同理,这一段输出:
int arr[]={6,7,8,9,10};

int *ptr=arr;

*(ptr++)=*(ptr++)+123;

printf("%d,%d,%d",*ptr++,*(++ptr),*(++ptr));
为10,10,9

#13


第二题有问题,C/C++标准中对于赋值操作的计算顺序未做规定。
因此,像第二题这样的写法,结果都是未定义的,跟具体的C编
译器实现相关,本题就给出一个操作系统约束,实在看不出结果
应该为什么,不应该为什么

#14


受教

#15


同楼上 这个跟具体编译器相关 很有意义吗?

#16


这个跟编译器入栈顺序有很大关系。
所以,不同编译器测试结果就会不一样。
即使是相同编译器,利用debug和release模式编译后,
结果可能就是不一样。

#17


第2题应该是 9, 9

和 语言标准无关, 注意都是 ptr ++, 所以所有赋值结果都不会是发生在 ptr自增后所指的地址上,那就只用看 ptr ++ 发生几次就可以了, 前一表达式 发生两次,最后  printf 发生一次,所以三次, 于是 9, 9

#18


即使是相同编译器,利用debug和release模式编译后, 

老实说,很不同意。
debug 和 release 发生在源码区别上,至少 vc 如此, 编译器都是一样编译的,怎么可能不同?
除非发生以下情况

#ifdef _DEBUG
operator ++(a, 0){
 ...
}
#else
operator ++(a, 0){
 ...
}
#endif

#19


1,在pritf语句中,表达式从右向左计算。

2,++ptr是在printf执行过程之中计算的。

3,ptr++是在printf执行完成以后计算的。

4,以下四个表达式执行之后结果一样的:

*(ptr++)=*(ptr++)+123;
*(++ptr)=*(++ptr)+123;
*(++ptr)=*(ptr++)+123;
*(ptr++)=*(++ptr)+123;

5,下面这个表达式和上面的四个执行之后结果是不一样的,:

*(ptr++)+=123;      //为什么不一样?或者用堆栈的前序表达式和后序表达式能够说清楚吧!

#20


zylthinking() 

我用不同的编译模式得出结果是不一样的!

(1) Debug
8,8
8,8

(1) release
8,8
9,8

(2) 都是 9,9




#21


*(ptr++)+=123;      //为什么不一样?

#22


我也感觉这种问题没有意义。
顺便说一下有个题问一个字占几个字节,他们的答案是2。

#23


哦,错了,他们的答案是4。

#24


跟编译器有关。
赋值符号的求值顺序没有定义,我写过一片关于这方面的帖子:
http://community.csdn.net/Expert/topic/4625/4625363.xml?temp=.1723139

#25


*(ptr++)+=123; 等价代码为
*ptr = *ptr + 123;
ptr++;
而*(ptr++)=*(ptr++)+123; 等价为
*ptr = *ptr + 123;
ptr++;
ptr++;
再因为调用printf的时候是从右向左压栈,因此先计算后面的表达式。
所以会有以上结果

#26


新手弱弱的提问:
*(ptr++)+=123; 执行后,*ptr应该为130吧,可是上面大部分人为什么说是8呢,高手出来解释一下,谢谢!

#27


c开发

#28


8    printf("line11%d,%d",*ptr,*(++ptr));
9    printf("line22%d,%d",*ptr,*(ptr++));

cl /FA 的输出(vs2k5,32-bit):
; Line 8
    mov edx, DWORD PTR _ptr$[ebp]    ; ptr->edx
    add edx, 4                       ; ++ptr
    mov DWORD PTR _ptr$[ebp], edx    ; ++ptr->ebp
    mov eax, DWORD PTR _ptr$[ebp]    ; (++ptr)->eax
    mov ecx, DWORD PTR [eax]         ; *(++ptr)
    push ecx                         ; push 8
    mov edx, DWORD PTR _ptr$[ebp]    ; ptr->edx
    mov eax, DWORD PTR [edx]         ; *ptr->eax
    push eax                         ; push 8
    push OFFSET $SG2223              ; 'line11%d,%d'
    call _printf
    add esp, 12; 0000000cH
; Line 9
    mov ecx, DWORD PTR _ptr$[ebp]    ; ptr->ecx
    mov edx, DWORD PTR [ecx]         ; *ptr->edx
    mov DWORD PTR tv72[ebp], edx     ; 8
    mov eax, DWORD PTR tv72[ebp]     ; 8->eax
    push eax                         ; push 8
    mov ecx, DWORD PTR _ptr$[ebp]    ; ptr->ecx
    mov edx, DWORD PTR [ecx]         ; *ptr->edx
    push edx                         ; push 8
    push OFFSET $SG2224              ; 'line22%d,%d'
    call _printf
    add esp, 12                      ; 0000000cH
    mov eax, DWORD PTR _ptr$[ebp]
    add eax, 4                       ; ptr++,这个顺序不定
    mov DWORD PTR _ptr$[ebp], eax
输出是line118,8line228,8。看了偶的注释就明白了,add eax,4这句出现的顺序跟编译选项有关。

gcc -S -g的结果(mingw32, gcc3.4.4):
LM6:
    leal -44(%ebp), %eax
    addl $4, (%eax)
    movl -44(%ebp), %eax
    movl (%eax), %eax
    movl %eax, 8(%esp)
    movl -44(%ebp), %eax
    movl (%eax), %eax
    movl %eax, 4(%esp)
    movl $LC0, (%esp)
    call _printf
.stabn 68,0,9,LM7-_main
LM7:
    movl -44(%ebp), %eax
    movl (%eax), %eax
    movl %eax, 8(%esp)
    leal -44(%ebp), %eax
    addl $4, (%eax)
    movl -44(%ebp), %eax
    movl (%eax), %eax
    movl %eax, 4(%esp)
    movl $LC1, (%esp)
    call _printf
输出是line118,8line229,8。这个应该可以看懂了

#29


楼上对编译了解得挺清楚啊,高手!向你学习!

#30


TO 新手弱弱的提问:
   //*(ptr++)+=123; 执行后,*ptr应该为130吧,可是上面大部分人为什么说是8呢

    *(ptr++)+=123;执行后,ptr是指向arr[1],但+123的是arr[0]。arr[0]=129。
所以*ptr=7。
     这样理解对么?

#31


真的是华为出的题吗
说实话这属于不良代码,即使没有歧义,也会造成误解,应该避免的

#32


1:// 8,8
   //9,8
2: //9,9
*(ptr++)+=123;这句有点迷惑人的感觉

#33


这种题很无聊,大家不要在这上面浪费时间。现在的发展潮流就是清晰,严谨。在这些与编译器有关的东西上面花太多时间没用。

#34


恩,学习.

#35


真确答案到底是多少
好像 第一题 8 8
8 8
第二题 9 9

#36


受益很多啊~~`

#37


无聊,真的很无聊,有研究这些不确定性的依赖于实现的问题的时间。不如去做点有意义的事情!

#38


windowsxp vs6.0 调试结果

1题:
8,8
8,8

2题:
9,9

#39


我把帖子转到技术区了。
http://community.csdn.net/Expert/topic/4625/4625363.xml?temp=.7333338

#40


华为出这种题??出题人脑子坏了。

#41


line118,8line228,8

#42


mark

#43


mark

#1


up

#2


我没有实际上机试,只是根据自己的理解猜的。

第1题:
line11 8,8
line22 9,8
因为调用printf的时候是从右向左压栈,因此先计算后面的表达式。

第二题:
9,9

#3


楼上分析完全正确!

#4


up

#5


因为调用printf的时候是从右向左压栈,因此先计算后面的表达式。

这句话要记住

#6


因为调用printf的时候是从右向左压栈,因此先计算后面的表达式。
这句话要记住
---------
哦,记住了

#7


不过我的输出是:
第1题:
line11 8,8
line22 8,8

#8


但输出结果是line118,8  line228,8真奇怪.谁能解释一下吗?
第二题为9,9.

#9


第一题的正确结果应该是
line11 8,8
line22 8,8

#10


line 8,8 输出后*ptr就是指向8
在第二个printf时候,ptr++是在整个printf以后才计算的,所以都是8

#11


谢谢~  受益fei浅~

#12


同理,这一段输出:
int arr[]={6,7,8,9,10};

int *ptr=arr;

*(ptr++)=*(ptr++)+123;

printf("%d,%d,%d",*ptr++,*(++ptr),*(++ptr));
为10,10,9

#13


第二题有问题,C/C++标准中对于赋值操作的计算顺序未做规定。
因此,像第二题这样的写法,结果都是未定义的,跟具体的C编
译器实现相关,本题就给出一个操作系统约束,实在看不出结果
应该为什么,不应该为什么

#14


受教

#15


同楼上 这个跟具体编译器相关 很有意义吗?

#16


这个跟编译器入栈顺序有很大关系。
所以,不同编译器测试结果就会不一样。
即使是相同编译器,利用debug和release模式编译后,
结果可能就是不一样。

#17


第2题应该是 9, 9

和 语言标准无关, 注意都是 ptr ++, 所以所有赋值结果都不会是发生在 ptr自增后所指的地址上,那就只用看 ptr ++ 发生几次就可以了, 前一表达式 发生两次,最后  printf 发生一次,所以三次, 于是 9, 9

#18


即使是相同编译器,利用debug和release模式编译后, 

老实说,很不同意。
debug 和 release 发生在源码区别上,至少 vc 如此, 编译器都是一样编译的,怎么可能不同?
除非发生以下情况

#ifdef _DEBUG
operator ++(a, 0){
 ...
}
#else
operator ++(a, 0){
 ...
}
#endif

#19


1,在pritf语句中,表达式从右向左计算。

2,++ptr是在printf执行过程之中计算的。

3,ptr++是在printf执行完成以后计算的。

4,以下四个表达式执行之后结果一样的:

*(ptr++)=*(ptr++)+123;
*(++ptr)=*(++ptr)+123;
*(++ptr)=*(ptr++)+123;
*(ptr++)=*(++ptr)+123;

5,下面这个表达式和上面的四个执行之后结果是不一样的,:

*(ptr++)+=123;      //为什么不一样?或者用堆栈的前序表达式和后序表达式能够说清楚吧!

#20


zylthinking() 

我用不同的编译模式得出结果是不一样的!

(1) Debug
8,8
8,8

(1) release
8,8
9,8

(2) 都是 9,9




#21


*(ptr++)+=123;      //为什么不一样?

#22


我也感觉这种问题没有意义。
顺便说一下有个题问一个字占几个字节,他们的答案是2。

#23


哦,错了,他们的答案是4。

#24


跟编译器有关。
赋值符号的求值顺序没有定义,我写过一片关于这方面的帖子:
http://community.csdn.net/Expert/topic/4625/4625363.xml?temp=.1723139

#25


*(ptr++)+=123; 等价代码为
*ptr = *ptr + 123;
ptr++;
而*(ptr++)=*(ptr++)+123; 等价为
*ptr = *ptr + 123;
ptr++;
ptr++;
再因为调用printf的时候是从右向左压栈,因此先计算后面的表达式。
所以会有以上结果

#26


新手弱弱的提问:
*(ptr++)+=123; 执行后,*ptr应该为130吧,可是上面大部分人为什么说是8呢,高手出来解释一下,谢谢!

#27


c开发

#28


8    printf("line11%d,%d",*ptr,*(++ptr));
9    printf("line22%d,%d",*ptr,*(ptr++));

cl /FA 的输出(vs2k5,32-bit):
; Line 8
    mov edx, DWORD PTR _ptr$[ebp]    ; ptr->edx
    add edx, 4                       ; ++ptr
    mov DWORD PTR _ptr$[ebp], edx    ; ++ptr->ebp
    mov eax, DWORD PTR _ptr$[ebp]    ; (++ptr)->eax
    mov ecx, DWORD PTR [eax]         ; *(++ptr)
    push ecx                         ; push 8
    mov edx, DWORD PTR _ptr$[ebp]    ; ptr->edx
    mov eax, DWORD PTR [edx]         ; *ptr->eax
    push eax                         ; push 8
    push OFFSET $SG2223              ; 'line11%d,%d'
    call _printf
    add esp, 12; 0000000cH
; Line 9
    mov ecx, DWORD PTR _ptr$[ebp]    ; ptr->ecx
    mov edx, DWORD PTR [ecx]         ; *ptr->edx
    mov DWORD PTR tv72[ebp], edx     ; 8
    mov eax, DWORD PTR tv72[ebp]     ; 8->eax
    push eax                         ; push 8
    mov ecx, DWORD PTR _ptr$[ebp]    ; ptr->ecx
    mov edx, DWORD PTR [ecx]         ; *ptr->edx
    push edx                         ; push 8
    push OFFSET $SG2224              ; 'line22%d,%d'
    call _printf
    add esp, 12                      ; 0000000cH
    mov eax, DWORD PTR _ptr$[ebp]
    add eax, 4                       ; ptr++,这个顺序不定
    mov DWORD PTR _ptr$[ebp], eax
输出是line118,8line228,8。看了偶的注释就明白了,add eax,4这句出现的顺序跟编译选项有关。

gcc -S -g的结果(mingw32, gcc3.4.4):
LM6:
    leal -44(%ebp), %eax
    addl $4, (%eax)
    movl -44(%ebp), %eax
    movl (%eax), %eax
    movl %eax, 8(%esp)
    movl -44(%ebp), %eax
    movl (%eax), %eax
    movl %eax, 4(%esp)
    movl $LC0, (%esp)
    call _printf
.stabn 68,0,9,LM7-_main
LM7:
    movl -44(%ebp), %eax
    movl (%eax), %eax
    movl %eax, 8(%esp)
    leal -44(%ebp), %eax
    addl $4, (%eax)
    movl -44(%ebp), %eax
    movl (%eax), %eax
    movl %eax, 4(%esp)
    movl $LC1, (%esp)
    call _printf
输出是line118,8line229,8。这个应该可以看懂了

#29


楼上对编译了解得挺清楚啊,高手!向你学习!

#30


TO 新手弱弱的提问:
   //*(ptr++)+=123; 执行后,*ptr应该为130吧,可是上面大部分人为什么说是8呢

    *(ptr++)+=123;执行后,ptr是指向arr[1],但+123的是arr[0]。arr[0]=129。
所以*ptr=7。
     这样理解对么?

#31


真的是华为出的题吗
说实话这属于不良代码,即使没有歧义,也会造成误解,应该避免的

#32


1:// 8,8
   //9,8
2: //9,9
*(ptr++)+=123;这句有点迷惑人的感觉

#33


这种题很无聊,大家不要在这上面浪费时间。现在的发展潮流就是清晰,严谨。在这些与编译器有关的东西上面花太多时间没用。

#34


恩,学习.

#35


真确答案到底是多少
好像 第一题 8 8
8 8
第二题 9 9

#36


受益很多啊~~`

#37


无聊,真的很无聊,有研究这些不确定性的依赖于实现的问题的时间。不如去做点有意义的事情!

#38


windowsxp vs6.0 调试结果

1题:
8,8
8,8

2题:
9,9

#39


我把帖子转到技术区了。
http://community.csdn.net/Expert/topic/4625/4625363.xml?temp=.7333338

#40


华为出这种题??出题人脑子坏了。

#41


line118,8line228,8

#42


mark

#43


mark