【问题标题】:char * argv[] is an array of pointers or array of char stringschar * argv[] 是指针数组或 char 字符串数组
【发布时间】:2019-07-06 02:19:13
【问题描述】:

据我目前的理解, char * argv[] = {"abc", "def"}; 初始化一个包含 2 个 char 指针的数组。第一个指向"abc",第二个指向"def"。而名称argv也是一个指针,指向数组argv中的第一个指针。

为什么有人说argvchar 字符串数组呢? (如 K&R 的 C 编程语言)。它们不是指指向chars 的指针数组吗,本书也对此进行了解释。

如果我的假设是正确的,那么 printf("%s", argv[1]) 中的 %s 根本不期望 char string,而是指向 char string 的指针?

感谢您的耐心等待!

我读过的东西:

Pointer to Pointer with argv

C: Accessing the second argv via a pointer

【问题讨论】:

  • 在 C 中,字符串是“指向 char 的指针”,也就是 char *。我认为你发明了两个概念,但只有一个存在。
  • 在 C 中,字符串是一个以零结尾的字符数组。与所有其他数组一样,它通常衰减为指向其第一个元素(char * 类型)的指针。所有处理字符串的函数都期望有一个char *(或可能的const char *)类型的衰减指针。
  • 哦,有道理。我猜我把它和 Python 中的字符串搞混了。

标签: c argv


【解决方案1】:

正如在 C 标准中使用的那样,“字符串 是由第一个空字符终止并包括第一个空字符的连续字符序列”(C 2018 7.1.1 1)。它不是char *char * 可能指向字符串的第一个字符,有时在 C 标准中称为指向字符串的指针,但这是一个草率的术语,因为 char * 必然是指向字符的指针——没有指向“序列”意味着什么的技术定义,尽管我们可能会认为它意味着指向序列的第一个元素。

据我目前的理解,char * argv[] = {"abc", "def"}; 初始化了一个包含 2 个 char 指针的数组。

没错。

而名称argv也是一个指针,指向数组argv中的第一个指针。

鉴于问题中argv 的定义,这是不正确的。定义char * argv[] = {"abc", "def"};argv 定义为char * 的数组。它不是指针。

当数组用作sizeof或一元&的操作数时,它作为数组进行操作。 (此外,当数组用字符串字面量初始化时,字符串字面量被用作数组。)除这些情况外,当在表达式中使用数组时,它被转换为指向其第一个元素的指针。这种转换是自动的,并且很常见,以至于学生可能会将数组或数组的名称误认为是它转换为的指针。这是一个错误。数组不是指针。

为什么有人说argvchar 字符串的数组呢? (就像 K&R 的 C 编程语言一样)。

Kernighan 和 Ritchie 在任何一个版本的C 编程语言 中都没有在索引中为argv 列出的任何地方提到这一点。在 1978 年的第一版中,他们在第 110 页上说“第二个 (argv) 是指向包含参数的字符串数组的指针,每个字符串一个。”在 1988 年的第二版中,他们在第 114 页上说“第二个(argv,用于参数向量)是指向包含参数的字符串数组的指针,每个字符串一个。”该索引还列出了第 163 页的 argv,但这里只是顺便提及,指的是程序名称 argv[0]

请注意,它们将argv 称为指针而不是数组。这是因为mainargv 参数是一个指针。虽然可以用int main(int argc, char *argv[]) 声明,但声明为数组的参数会自动调整为指针。因此char *argv[]main 的声明中将argv 定义为与您显示的声明char * argv[] = {"abc", "def"}; 不同的东西。在参数声明中,自动调整为指针。在单独的定义中,它是一个数组。

尽管 Kernighan 和 Ritchie 确实将 argv 称为指针,而不是您所写的数组,但他们说它是“指向数组的指针”。这也是一个草率的术语。它的类型是pointer-to-pointer-to-char,而不是pointer-to-array-of-char。它只是一个指向数组的指针,仅在它是指向char 数组的第一个元素的意义上。

如果我的假设是正确的,那么 printf("%s", argv[1]) 中的 %s 根本不期望 char string,而是指向 char string 的指针?

根据 C 2018 7.21.6.1 8,对于不带修饰符或精度的 s 说明符到 printf,“参数应是指向字符类型数组的初始元素的指针。数组中的字符被写入(但不包括)终止空字符。”因此,应该传递一个指向字符串初始字符的char *(或signed char *unsigned char *)。

【讨论】:

    【解决方案2】:

    Char **argv 指向一个参数,以及该参数中的一个字符。

    例子:

    /* ************************************************************************** */
    /*                                                                            */
    /*                                                        :::      ::::::::   */
    /*   temp.c                                             :+:      :+:    :+:   */
    /*                                                    +:+ +:+         +:+     */
    /*   By: albarret <marvin@42.fr>                    +#+  +:+       +#+        */
    /*                                                +#+#+#+#+#+   +#+           */
    /*   Created: 2019/07/05 20:14:37 by albarret          #+#    #+#             */
    /*   Updated: 2019/07/05 20:17:41 by albarret         ###   ########.fr       */
    /*                                                                            */
    /* ************************************************************************** */
    
    #include <unistd.h>
    
    void    ft_putchar(char c)
    {
        write(1, &c, 1);
    }
    
    int     main(int argc, char **argv)
    {
        int i;
    
        i = 0;
        if (argc < 2)
        {
            write(1, "\n", 1);
            return (0);
        }
        while (argv[1][i])
        {
            ft_putchar(argv[1][i]);
            i++;
        }
        write(1, "\n", 1);
        return (0);
    }
    

    【讨论】:

      猜你喜欢
      • 2018-04-05
      • 1970-01-01
      • 2021-01-26
      • 1970-01-01
      • 1970-01-01
      • 2021-05-23
      • 2020-11-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多