我最近一直在搞亂 C 并且我遇到了一些“奇怪”的行為
#include <stdio.h>
int main(int argc, char **argv) {
printf("&argv=%d\n&argv[0]=%d\n", &argv, &(argv[0]));
return 0;
}
指向 argv 的指標與 argv[0] 的指標完全不同,因為 C 陣列是連續的,指向 argv 的指標不應該與第一個 C 字串的開頭相同嗎?在我的腦海中,argv 應該是這樣的
char **argv = {char *, char *, char *};
其中 argv 陣列的開頭與第一個字串的開頭相同 這是如何構造的,為什么兩個指標不一樣?
uj5u.com熱心網友回復:
printf要求您使用與您傳遞的引數型別匹配的格式說明符。%d與您傳遞的引數的型別不匹配(它需要int或類似),因此程式的行為是未定義的。
我建議一般避免printf(編輯:問題曾經被標記為 [c ]),但如果你必須使用它,那么你可以使用%p格式說明符 for void*. 您必須將指標引數轉換為void*.
修復程式后,您會發現地址確實不同。解釋是這argv是一個不指向自身的指標。因此,它的值與存盤位置不同。它指向存盤在別處的另一個物件。
... argv 陣列 ...
argv不是陣列。函式引數不能是陣列。argv是一個指標。
您可以創建一個類似的結構,如下所示:
char args[] = "./a.out\0example\0argument";
char* ptrs[] = {
args 0,
args 8,
args 16,
0,
};
int argc = 3;
char** argv = ptrs;
// argv == &ptrs[0]
// argv != &argv
uj5u.com熱心網友回復:
C 陣列是連續的,但一方面您獲取了陣列的地址,另一方面您獲取了陣列中的地址。
如果您列印出像這樣argv[i]的所有值的值,這可能會更明顯i:
$ cat pointer.c
#include <stdio.h>
int main(int argc, char** argv) {
int i;
for (i = 0; i < argc; i) {
printf("&argv=%p\targv=%p\t&argv[%d]=%p\n", &argv, argv, i, &(argv[i]));
}
return 0;
}
$ gcc pointer.c
$ ./a.out 1 2 3
&argv=0x7ff7b3716690 argv=0x7ff7b37167e0 &argv[0]=0x7ff7b37167e0
&argv=0x7ff7b3716690 argv=0x7ff7b37167e0 &argv[1]=0x7ff7b37167e8
&argv=0x7ff7b3716690 argv=0x7ff7b37167e0 &argv[2]=0x7ff7b37167f0
&argv=0x7ff7b3716690 argv=0x7ff7b37167e0 &argv[3]=0x7ff7b37167f8
雖然%p是一個更好的格式說明符,%d但如果您列印出陣列第一個元素的地址(只是argv)而不是指向陣列第一個元素的地址的指標(即&argv和不是你的意思)。
uj5u.com熱心網友回復:
由于 C 陣列是連續的,指向 argv 的指標不應該與第一個 C 字串的開頭相同嗎?
陣列的地址確實與其第一個元素的地址相同,是的。但argv不是陣列,它是指向陣列的指標。 &argv是指標本身的地址,而不是它指向的陣列的地址。自行評估argv將回傳陣列的地址。因此,&(argv[0])是陣列第一個元素的地址。
試試這個,你會看到argv和&argv是兩個不同的地址:
printf("&argv=%p\nargv=%p\n&argv[0]=%p\n", &argv, argv, &(argv[0]));
uj5u.com熱心網友回復:
對于初學者,您應該使用轉換說明符%p來使用函式輸出指標printf。
函式引數是函式的區域變數。
您可以通過以下方式想象函式 main
int main( /*int argc, char** argv */) {
int argc = some_argument expression;
char **argv = some_argument_expression;
//...
因此運算式&argv給出了區域變數的地址argv
運算式是型別argv[0]為 的區域變數所指向的陣列的第一個元素。該運算式給出了指向陣列的第一個元素的地址。argvchar **&argv[0]
在 main 中作為引數定義&argv的區域變數的地址也是如此。argvWhile&argv[0]是在函式 main 之外定義的陣列的第一個元素的地址。
為了更清楚,考慮一個非常簡單的程式。
#include <stdio.h>
int main* void )
{
int a[] = { 1, 2, 3, 4, 5 };
int *p = a;
printf( "&p = %p, &p[0] = %p\n", ( void * )&p, ( void * )&p[0] );
}
如您所見,運算式p 產生占用其自身記憶體范圍&的變數的地址,而運算式產生占用單獨記憶體范圍的陣列的第一個元素的地址。p&p[0]a
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/440254.html
標籤:C
上一篇:功能中的錯誤(?),我不明白
