我把argv[]定义为char *,使用下面的printf语句:
printf("%s\n",argv[1]); // prints out the entire string
printf("%p\n",&argv[1]); // & -> gets the address
printf("%c\n",argv[1][0]);// prints out the first char of second var
printf("%c\n",*argv[1]); //
最后一个我不明白,打印*argv[1]
是什么意思,为什么它和*argv[1][0]
不一样,为什么你不能打印出printf("%s\n",*argv[1]);
,还有,为什么&*argv[1]
和&argv[1]
是不同的地址?
5条答案
按热度按时间2skhul331#
数组下标操作
a[i]
定义为*(a + i)
-给定地址a
,从该地址偏移i
个元素(* 不是字节 *)并解引用结果。因此,给定指针p
,*p
等价于*(p + 0)
,*(p + 0)
等价于p[0]
。argv
的类型为char **
;有鉴于此,以下所有情况都是正确的:由于
argv[i][j]
的类型是char
,因此*argv[i][j]
不是有效的表达式。下面是
argv
序列的一个糟糕的可视化:这可能有助于解释不同表达式的结果。
nom7f22z2#
argv
是字符指针的数组(1)。所以它是普通数组,只是数组的每个元素都是一个指针。argv[0]
是一个指针,argv[1]
,等等。argv[0]
-数组中的第一个元素。因为数组中的每个元素都是字符指针,所以它的值也是字符指针(正如我们上面提到的)。*argv[1]
-这里argv[1]
是上述数组中的第二个元素,但argv[1]
也是一个字符指针。应用*
只是解引用该指针,您将获得argv[1]
指向的字符串中的第一个字符。您应该使用%c
打印它,因为这只是一个字符。argv[1][0]
已经是数组中第二个字符串的第一个字符-所以没有更多的空间来解引用。(1)严格来说,它是指针到指针的,但也许你可以把它看作是指针数组。无论如何,这里有更多关于它的信息:https://stackoverflow.com/a/39096006/3963067
62lalag43#
如果
argv[1]
是指向char
的指针,那么*argv[1]
解引用该指针,并获取字符串在argv[1]
处的第一个字符,因此它与argv[1][0]
相同,并使用"%c"
说明符打印。argv[1][0]
本身就是一个char
,而不是一个指针,所以它是不可取消引用的。izkcnapc4#
1.这不是特定于
char *
的。1.您可以简化 *ptr和ptr[0]之间的区别。
1.因为ptr[0]是 *(ptr + 0)或 *ptr的糖,所以没有区别,因为
+ 0
是无用的。因为
%p
说明符需要一个void *
,在正常情况下C会自动将指针提升到void *
,但是printf()
使用变量参数列表。如果你愿意,我让你读doc。但是char *
不会被提升为void *
,就像我说的printf()
,除了void *
,所以如果你不自己强制转换,你会有一个未定义的行为。ou6hu8tu5#
最后一行
printf("%c\n",*argv[1]);
既解引用argv
又访问数组索引1
,换句话说,这是在执行argv[1][0]
,就像前一行一样,因为数组下标访问[1]
的优先级高于解引用操作符(*
)。但是,如果要将最后一行中的表达式括起来,以便首先处理取消引用运算符,则应执行以下操作:
现在,当您运行程序时,输出的最后一行将是
argv[0][1]
而不是[1][0]
,即您用来执行程序的命令行中的第二个字符。