我無法理解這種意外的 C 行為,其中列印argv[0]列印./a.out而不是實際內容argv[0]應該是記憶體地址,因為argv它是一個指標陣列。
如果我創建一個名為的陣列,char name[] = "hello"那么我希望看到h并且name[0]如果char * argv[]持有,例如 3 個指標(記憶體地址),那么邏輯上argv[0]應該是一個記憶體地址。
我的理由是,如果我想訪問argv[0]指向我應該需要做的記憶體地址的實際內容*(argv[0])。這里發生了什么?C在這里做了某種魔術嗎?
------ ------ ------ --- --- ----
| h | e | l | l | o | \0 |
------ ------ ------ --- --- ----
^---- name[0] = h
------ ------ ------
| 0xA7 | 0xCE | 0xC4 |
------ ------ ------
^---- argv[0] = should be 0XA7 (the value of `argv[0]`,
not the value it points to
#include <stdio.h>
int main(int argc, char * argv[]) {
char name[] = "hello";
printf("%c \n", name[0]); // expected h
printf("%s \n", argv[0]); // expected 0xA7 (but got ./a.out instead)
}
$ gcc main.c
$ ./a.out arg1 arg2 arg3
uj5u.com熱心網友回復:
我的理由是,如果我想訪問 argv[0] 指向的記憶體地址的實際內容,我應該需要執行 *(argv[0])。這里發生了什么?
printf正在取消參考。當傳遞"%s"一個指標(地址)時,printf不列印地址。它列印地址中的內容。具體來說,它會列印ptr[0],等ptr[1],ptr[2]直到遇到零。
(請記住,這ptr[i]與 相同*(ptr i)。我將使用前者,因為它更清潔。)
讓我們從一個更簡單的例子開始。
char *name = "hello";
printf( "%s", name );
name
------------------- ----- ----- ----- ----- ----- -----
| [Some address 1] -------->| 'h' | 'e' | 'l' | 'l' | 'o' | 0 |
------------------- ----- ----- ----- ----- ----- -----
傳遞"%s", name傳遞包含陣列%s?的地址和name("[Some address 1]") 包含的地址。后者是包含 的陣列的地址hello?。
這告訴printf列印name[0]( h)、name[1]( e)、name[2]( l) 等,直到遇到零。
現在讓我們看看你的情況。
argv
------------------- ------------------- ----- ----- ----- ----- ----- ----- ----- -----
| [Some address 2] -------->| [Some address 3] -------->| '.' | '/' | 'a' | '.' | 'o' | 'u' | 't' | 0 |
------------------- ------------------- ----- ----- ----- ----- ----- ----- ----- -----
| [Some address 4] -------->| 'a' | 'r' | 'g' | '1' | 0 |
------------------- ----- ----- ----- ----- -----
| [Some address 5] -------->| 'a' | 'r' | 'g' | '2' | 0 |
------------------- ----- ----- ----- ----- -----
| [Some address 6] -------->| 'a' | 'r' | 'g' | '3' | 0 |
------------------- ----- ----- ----- ----- -----
| NULL |
-------------------
要不就
argv[0]
------------------- ----- ----- ----- ----- ----- ----- ----- -----
| [Some address 3] -------->| '.' | '/' | 'a' | '.' | 'o' | 'u' | 't' | 0 |
------------------- ----- ----- ----- ----- ----- ----- ----- -----
傳遞"%s", argv[0]傳遞包含陣列%s?的地址和argv[0]("[Some address 3]") 包含的地址。后者是包含 的陣列的地址./a.out?。
這告訴printf列印argv[0][0]( .)、argv[0][1]( /)、argv[0][2]( .) 等,直到遇到零。
uj5u.com熱心網友回復:
對于宣告為的陣列
char name[] = "hello";
運算式name[0]具有型別,并且在 printf 呼叫中char使用轉換說明符c
printf("%c \n", name[0]);
陣列的第一個元素作為字符輸出。
這個陣列的宣告
char * argv[]
用作引數宣告由編譯器調整為宣告
char **argv
并且運算式argv[0]具有型別char *。
轉換說明符s旨在輸出由相應引數指向的字串,如下所示
printf("%s \n", argv[0]);
argv[0]指向一個包含運行程式名稱的字串。
如果要將運算式輸出為地址,則需要撰寫
printf("%p \n", ( void * )argv[0]);
為了更清楚地考慮這個宣告
printf( "%s\n", "Hello" );
我認為您期望的輸出是
Hello
字串文字的型別為char[6]。但是在 printf 呼叫中用作運算式時,它會隱式轉換為指向其 type 的第一個元素的指標char *。
所以 printf 呼叫的第二個引數的型別與呼叫中char *的相同
printf("%s \n", argv[0]);
其中第二個運算式也有型別char *。
uj5u.com熱心網友回復:
%s告訴printf“從您傳遞的地址加載字符并從那里列印字符,直到找到一個空字符。”
使用%s,printf不會列印或格式化它傳遞的地址。它使用地址來訪問記憶體。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/519681.html
標籤:C指针打印命令行参数
下一篇:為什么我能夠更改C中的字串常量?
