1

我将 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]呢?

4

5 回答 5

4
char *argv[]

argv是 char 指针的数组(1)。所以它是普通数组,只是数组的每个元素都是一个指针。argv[0]是一个指针argv[1],等等。

argv[0]- 数组中的第一个元素。由于数组中的每个元素都是 char 指针,因此 this 的值也是一个 char 指针(正如我们上面已经提到的)。

*argv[1]- 现在这argv[1]是上述数组中的第二个元素,但argv[1]也是一个字符指针。应用*只是取消引用指针,你会得到字符串中指向的第一个字符argv[1]。您应该使用%c它来打印它,因为这只是一个字符。

argv[1][0]已经是数组中第二个字符串的第一个字符 - 所以没有更多的取消引用空间。这与之前的基本相同。


(1) 严格地说它是指向指针的指针,但也许你可以“认为”它是指针数组。无论如何,这里有更多关于它的信息:https ://stackoverflow.com/a/39096006/3963067

于 2017-01-15T18:02:05.453 回答
4

数组下标操作a[i]定义为*(a + i)- 给定地址a,从该地址偏移i元素(不是字节)并取消引用结果。因此,给定一个指针p*p等价于*(p + 0),这等价于p[0]

的类型argvchar **; 鉴于此,以下所有情况都是正确的:

    Expression         Type            Value
    ----------         ----            -----
          argv         char **         Pointer to a sequence of strings
         *argv         char *          Equivalent to argv[0]
        **argv         char            Equivalent to argv[0][0]
       argv[i]         char *          Pointer to a single string
      *argv[i]         char            Same as argv[i][0]
    argv[i][j]         char            j'th character of i'th string
      &argv[i]         char **         Address of the pointer to the i'th string

由于argv[i][j]is的类型char*argv[i][j]不是有效的表达式。

这是argv序列的糟糕可视化:

     +---+              +---+                                         +---+
argv |   | ---> argv[0] |   | ---------------------------> argv[0][0] |   |
     +---+              +---+                     +---+               +---+
                argv[1] |   | -------> argv[1][0] |   |    argv[0][1] |   |
                        +---+                     +---+               +---+
                         ...           argv[1][1] |   |                ...
                        +---+                     +---+               +---+
             argv[argc] |   | ---|||               ...   argv[0][n-1] |   |
                        +---+                     +---+               +---+
                                     argv[1][m-1] |   |
                                                  +---+

这可能有助于解释不同表达式的结果。

于 2017-01-15T21:16:23.947 回答
3

如果argv[1]是指向 的指针char,则*argv[1]取消引用该指针并在 处获取字符串的第一个字符argv[1],因此它与使用格式说明符argv[1][0]打印并打印。"%c"

argv[1][0]是一个char本身,而不是一个指针,所以它是不可解引用的。

于 2017-01-15T18:02:15.213 回答
2

最后一行printf("%c\n",*argv[1]);是取消引用argv和访问数组 index 1。换句话说,argv[1][0]就像上一行一样,这是在做 ,因为数组下标访问[1]优先级高于解引用运算符 ( *)。

但是,如果您要将最后一行中的表达式括起来以使取消引用运算符首先被处理,您可以这样做:

printf("%c\n", (*argv)[1]);

现在,当您运行程序时,输出的最后一行将argv[0][1]代替[1][0],即用于执行程序的命令行中的第二个字符。

于 2017-01-15T18:02:07.813 回答
2
  1. 这不是特定于char *.
  2. 您可以通过 *ptr 和 ptr[0] 之间的区别来简化。
  3. 没有区别,因为 ptr[0] 是 *(ptr + 0) 或 *ptr 的糖,因为+ 0它是无用的。

// printf("%p\n", &argv[1]); is wrong you must cast to (void *)
printf("%p\n", (void *)&argv[1]);

因为%p说明符期望 a void *,在正常情况下 C 会自动将您的指针提升到void *printf()使用变量参数列表。这有很多规则,如果你愿意,我让你阅读文档。但是不会像我说char *的那样被提升,除非你自己不施放它,否则你有一个未定义的行为。void *printf()void *

于 2017-01-15T18:02:43.287 回答