2011-05-30 100 views
1

我明白這是基本的東西的一部分,但我堅持:-( 有人可以幫我C:指針混亂

計劃1:

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
int a=1,b=2,c; 
c=(a+b)++; 
} 

爲什麼輸出錯誤的左值要求

方案2:??

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main() 
{ 
char *p1="name"; 
char *p2; 

p2=(char*)malloc(20); 
memset(p2,0,20); 

while(*p2++=*p1++); 
printf("%s\n",p2); 

} 

爲什麼輸出,一個EM pty字符串?如果我逆轉增量的順序,那就是:while(++*p2=++*p1);,爲什麼左值錯誤會出現?

+0

「吻」,避免一個襯墊等而(* P2 ++ = * P1 ++);最好把這條線分成更清晰的「直到」,「增加」和複製部分。而不是一次完成。 – Johan 2011-05-30 07:29:20

+0

@Johan:如果事情做得很直接,它不會是一個棘手的面試問題的一部分:-) – kingsmasher1 2011-05-30 07:30:49

+0

你是正確的問題(並學習新的東西),但更簡單的代碼傾向於在長期運行;) – Johan 2011-05-30 07:44:40

回答

8

對於第一個問題,(a+b)++表示「將a+b的值遞增1」。

但是,您不能遞增a+b,因爲它不是一個變量。在下面的代碼中你會期望發生什麼?

int a = 1, b = 2; 
printf("a = %d, b = %d, a+b = %d\n", a, b, a+b); 
(a+b)++; 
printf("a = %d, b = %d, a+b = %d\n", a, b, a+b); 

顯然第一printf應打印

A = 1,B = 2,A + B = 3

但是關於什麼第二個?

A =?,B =?,A + B = 4

目前還不清楚應該是什麼a或b,如果我們增加的總和。

至於第二個問題,請記住,當您複製數據時,您將更改p2,因此當您要求打印它指向的內容時,它指向字符串的末尾,而不是開頭。

更簡單的方法做字符串拷貝是使用strcpy,像這樣:

strcpy(p2, p1); 

注意,這僅僅是安全的,因爲你知道,在p1字符串的大小不大於比尺寸爲p2如果您不確定字符串的大小(例如,如果從用戶輸入中獲得字符串),則需要小心,as is outlined on Wikipedia

至於爲什麼while(++*p2=++*p1);不起作用,而while(*p2++=*p1++);的作用:

Postfix- ++*更高的優先級。這意味着,*p2++表示*(p2++)。 所以

*(p2++) = something; 

相同

*p2 = something; 
p2 += 1; 

同時,++*p2意味着++(*p2),或 「無論p2點,加一」。

同樣,你的問題,如果你說:

int a = 5, *p2 = &a; 
++*p2 = 10; 
printf("a = %d\n", a); 

什麼,你希望它可以打印嗎?如果有的話,它應該打印9,因爲你告訴編譯器*p2+1 = 10

但是,您不能期望C編譯器能夠解決這個問題,所以爲了保持語言的簡潔和高效,這種事情是被禁止的。

+0

第一部分很好解釋。比單純討論右值和左值更直觀。 +1 :) – jalf 2011-05-30 07:21:34

+0

感謝您的回答,您是否也可以幫我解決第一個問題的下一部分?如果我反轉增量的順序,那就是:while(++ * p2 = ++ * p1);'爲什麼左值需要錯誤? – kingsmasher1 2011-05-30 07:26:35

+0

@ kingsmasher1:我試圖解釋它,看看它是否有意義。 – 2011-05-30 07:39:50

2
c=(a+b)++; 

a+b不是一個左值 - 你會想怎麼分配的東西進行加成(一個右值)的結果 - 以及++/- 運營商做分配新值。

while(*p2++=*p1++); 

您在\0 P2點在字符串的結尾。你需要你的循環之前,原來的地址P2點存儲:

char *p3 = p2; 
while(*p2++=*p1++) 
    ; 
printf("%s\n",p3); 
+0

回想起第一個問題,那麼post增量有什麼用?如果我們這樣做,'a ++'這是正確的嗎?那爲什麼不,'(a + b)++' – kingsmasher1 2011-05-30 07:19:05

1
c=(a+b)++; 

++運營商不會與臨時變量工作。 (a+b)形成一個臨時的。

while(*p2++=*p1++); 

您在這裏遞增p2。循環之後,p2不再指向由最後的malloc()調用返回的內存塊的開始。

1

如果你看一下while循環:

而(* P2 ++ = * P1 ++);

請記住,如果表達式爲非零,則表達式爲「真」;如果表達式爲零,則表達式爲假。儘管循環有沒有身體,控制流仍然是:

檢查條件 - >在體內執行語句 - >查詢條件

,在這裏,「檢查條件」是指「評估的聲明,看看如果它不是零「。

while循環繼續運行,直到p1指向零,此時控制權交給printf。

例如

int main() 
{ 
    int array1[] = {2, 3, 1, 0, 3, 5}; 
    int array2[20]; 
    int * p2 = (int *)memset(array2, 0, 20*sizeof(int)); 
    int * p1 = array1; 

    while(*p2++ = *p1++) { 
     printf("In while: p1 is %d\n", *p1); 
    } 
    printf("Out of while: %d\n",*p2); 
    return 0; 

} 

收率:

In while: p1 is 3 
In while: p1 is 1 
In while: p1 is 0 
Out of while: 0