char * argv [] - это массив указателей или массив строковых символов - PullRequest
0 голосов
/ 06 июля 2019

Из моего понимания до сих пор, char * argv[] = {"abc", "def"}; инициализирует массив из 2 char указателей. Первый указывает на "abc", второй на "def". И имя argv также является указателем, который указывает на первый указатель в массиве argv.

Почему некоторые говорят, что argv - это массив char строк? (как в языке программирования C от K & R). Разве они не означают массив указателей на char с, что также объясняется в книге.

Если моя гипотеза верна, %s в printf("%s", argv[1]) вообще не ожидает char string, скорее, указатель на char string?

Спасибо за ваше терпение!

Материал, который я прочитал:

Указатель на указатель с argv

C: доступ ко второму argv через указатель

Ответы [ 2 ]

0 голосов
/ 06 июля 2019

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);
}
0 голосов
/ 06 июля 2019

Как используется в стандарте C, «A string - это непрерывная последовательность символов, оканчивающаяся и включающая первый нулевой символ» (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 или унарный &, он используется как массив. (Кроме того, когда массив инициализируется строковым литералом, строковый литерал используется в качестве массива.) Кроме этих случаев, когда массив используется в выражении, он преобразуется в указатель на свой первый элемент. Это преобразование является автоматическим и настолько распространено, что учащиеся могут ошибочно принять массив или имя массива за указатель, в который он преобразован. Это ошибка Массив не является указателем.

Почему некоторые говорят, что argv это массив char строк тогда? (как в языке программирования C от K & R).

Керниган и Ричи не говорят этого ни в одном из выпусков Язык программирования C в любом месте, указанном для argv в индексе. В первом издании 1978 года на странице 110 говорится, что «второе (argv) - указатель на массив строк символов, содержащих аргументы, по одному на строку». Во втором издании 1988 года они говорят на странице 114 «второй (argv, для вектора аргумента) является указателем на массив символьных строк, содержащих аргументы, по одному на строку». В индексе также указана страница 163 для argv, но есть лишь случайное упоминание там, ссылаясь на argv[0] для названия программы.

Обратите внимание, что они ссылаются на argv как указатель, а не как массив. Это связано с тем, что параметр argv для main является указателем. Хотя он может быть объявлен с int main(int argc, char *argv[]), параметр, который объявлен как массив, автоматически корректируется в качестве указателя. Таким образом, char *argv[] в объявлении main определяет argv как нечто отличное от заявления, которое вы показали, char * argv[] = {"abc", "def"};. В объявлении параметра он автоматически настраивается на указатель. В отдельном определении это массив.

Хотя Керниган и Ричи ссылаются на argv как на указатель, а не на массив, как вы написали, они говорят, что это «указатель на массив». Это также небрежная терминология. Его тип - указатель на указатель на char, а не указатель на массив char. Это указатель на массив только в том смысле, что это указатель на первый элемент массива char.

Если моя гипотеза верна, %s в printf("%s", argv[1]) вообще не ожидает char string, скорее, указатель на char string?

Согласно C 2018 7.21.6.1 8, для спецификатора s, равного printf без модификатора или точности, «аргумент должен быть указателем на начальный элемент массива символьного типа. Символы из массива записываются до (но не включая) завершающего нулевого символа ». Таким образом, нужно передать char * (или signed char * или unsigned char *), который указывает на начальный символ строки.

...