簡體   English   中英

使用指針和字符串打印 (C)

[英]printing with pointers and strings (C)

有人可以解釋為什么會打印出來:“d ce”我想我明白為什么它會打印出“d”,但我不明白“ce”

#include <stdio.h>

int main(void){
    char s1[]="abcd",*cp;

    cp=s1+2;
    printf("%c %s\n",(*(++cp))++,s1+2);

    return 0;
}

TL;博士

為了理解這段代碼,您需要相當深入的 C 序列點知識、未定義行為和雜項“語言律師”知識。 如果不是這種情況,那么只需忘記編寫或理解這樣的人工垃圾代碼,您就可以在此處停止閱讀。 高級解釋如下。


C11 6.5 規定:

如果標量 object 上的副作用相對於同一標量 object 上的不同副作用或使用相同標量 ZA8CFDE6331BD59EB2AC96F8911C4B66Z 的值的值計算未排序,則行為未定義如果表達式的子表達式有多個允許的排序,則如果在任何排序中出現這種未排序的副作用,則行為未定義。

通常這會呈現像這種未定義行為的奇怪代碼。 但在這種情況下, 1) s不是一個標量,而是一個聚合。 標量是s[3]左值。 並且 2) 使用 object 在同一表達式中更改值的)++增量不會不排序到另一個值計算。

(*(++cp))++s1+2彼此之間是無序的,但這對於為未定義的行為提供案例並不重要。

  • cp=s1+2; 這里cp指向'c'
  • 僅此表達式(*(++cp))++首先將指針增加一步以指向包含'd' s[3] 然后它取消引用指針,以便我們獲得值'd'
  • 然后它使用后綴 ++ 將值增加 1,這在大多數符號表中表示'e'
  • 值的 ++ 變化與s1+2期間發生的值計算無關,但這並不重要。
  • 在調用 function 之前評估所有 arguments 並且在參數列表的完整評估之后有一個序列點。
  • printf然后發現%s並取消對字符串的引用,這是一個值計算,但與前一個)++相關。 這打印ce
  • 最后在 function 返回之前還有另一個序列點。

所以代碼實際上是定義良好的,即使寫得很糟糕。

希望內聯評論說清楚。

#include <stdio.h>

int main()
{
    char s1[]="abcd",s2[]="cdef",s3[5],*cp;

    printf("s1 = %p\n", (void*)s1); // prints start address of s1
    
    cp = s1+2; // cp points to 2 chars advanced of s1 i.e 'c'
    
    printf("cp = %p\n", (void*)cp); // prints address at 'c'
    //first increment cp to point to next location, which now points at 'd' from 'c'
    //the outer ++ increments 'd' to 'e' post-fix, so first prints 'd'
    printf("(*(++cp))++ = %c\n", (*(++cp))++); 
                                               
    printf("s1 = %s\n", s1); // you will see "abce"
    printf("s1+2 = %s\n", s1+2); // 2 chars advanced of s1, i.e "ce"
    
    //printf("%c %s\n",(*(++cp))++,s1+2);

    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM