Каков тип аргумента командной строки `argv` в C?

Я читаю раздел от C Primer Plus о аргументе командной строки argv, и мне трудно понять это предложение.

В нем говорится, что

Программа хранит строки командной строки в памяти и сохраняет адрес каждой строки в массиве указателей. Адрес этого массив сохраняется во втором аргументе. По соглашению, этот указатель на указатели называются argv, для значений аргументов.

Означает ли это, что строки командной строки хранятся в памяти в виде массива указателей на массив из char?

Ответы

Ответ 1

Непосредственное цитирование из C11, глава §5.1.2.2.1/p2, запуск программы (основное внимание)

int main(int argc, char *argv[]) { /* ... */ }

[...] Если значение argc больше нуля, элементы массива argv[0] через argv[argc-1] включительно должен содержать указатели на строки, [...]

и

[...] и строки, на которые указывает массив argv [...]

Итак, в основном, argv является указателем на первый элемент массива строк note. Это можно сделать более ясным из альтернативной формы,

int main(int argc, char **argv) { /* ... */ }

Вы можете перефразировать это как указатель на первый элемент массива указателей на первый элемент массивов char с нулевым завершением, но я бы предпочел придерживаться строк.


Примечание:

Чтобы пояснить использование "указателя на первый элемент массива" в приведенном выше ответе, следуя §6.3.2.1/p3

За исключением случаев, когда это операнд оператора sizeof, оператор _Alignof или унарный & или строковый литерал, используемый для инициализации массива, выражение, которое имеет type '' типа типа преобразуется в выражение с указателем типа '', чтобы набирать такие точки к исходному элементу объекта массива и не является значением lvalue. [...]

Ответ 2

argv имеет тип char **. Это не массив. Это указатель на указатель на char. Аргументы командной строки хранятся в памяти, а адрес каждой ячейки памяти хранится в массиве. Этот массив представляет собой массив указателей на char. argv указывает на первый элемент этого массива.

                  Some
                  array

                 +-------+        +------+------+-------------+------+
argv ----------> |       |        |      |      |             |      |
                 | 0x100 +------> |      |      | . . . . . . |      |  Program Name1
         0x900   |       |        |      |      |             |      |
                 |       |        +------+------+-------------+------+
                 +-------+         0x100  0x101
                 |       |        +------+------+-------------+------+
                 | 0x205 |        |      |      |             |      |
         0x904   |       +------> |      |      | . . . . . . |      |  Arg1
                 |       |  .     |      |      |             |      |
                 +-------+        +------+------+-------------+------+
                 |  .    |  .      0x205  0x206
                 |  .    |
                 |  .    |  .
                 |  .    |
                 +-------+  .     +------+------+-------------+------+
                 |       |        |      |      |             |      |
                 | 0x501 +------> |      |      | . . . . . . |      |  Argargc-1
                 |       |        |      |      |             |      |
                 +-------+        +------+------+-------------+------+
                 |       |         0x501  0x502
                 | NULL  |
                 |       |
                 +-------+


0xXXX Represents memory address

<суб > 1. В большинстве случаев argv[0] представляет имя программы, но если имя программы недоступно в среде хоста, то argv[0][0] представляет нулевой символ.Суб >

Ответ 3

Эта нить - это крушение поезда. Вот ситуация:

  • Существует массив с argc+1 элементами типа char *.
  • argv указывает на первый элемент этого массива.
  • Существуют argc другие массивы типа char и различные длины, содержащие строки с нулевым завершающим символом, представляющие аргументы командной строки.
  • Элементы массива указателей каждый указывают на первый символ одного из массивов char; кроме последнего элемента массива указателей, который является нулевым указателем.

Иногда люди пишут "указатель на массив X", чтобы означать "указатель на первый элемент массива X". Вы должны использовать контексты и типы для определения того, действительно ли это означало это.

Ответ 4

Да, точно.

argv - это char** или char*[], или просто массив указателей char *.

Итак, argv [0] - это char* (строка), а argv[0][0] - char.

Ответ 5

Да.

Тип argv - char**, то есть указатель на указатель на char. В принципе, если вы считаете, что char* является строкой, то argv является указателем на массив строк.

Ответ 6

argv - массив указателей на символы.

Следующий код отображает значение argv, содержимое argv и выполняет дамп памяти в памяти, на которую указывает содержимое argv. Надеюсь, это освещает смысл косвенности.

#include <stdio.h>
#include <stdarg.h>

print_memory(char * print_me)
{
    char * p;
    for (p = print_me; *p != '\0'; ++p)
    {
        printf ("%p: %c\n", p, *p);
    }

    // Print the '\0' for good measure
    printf ("%p: %c\n", p, *p);

}

int main (int argc, char ** argv) {
    int i;

    // Print argv
    printf ("argv: %p\n", argv);
    printf ("\n");

    // Print the values of argv
    for (i = 0; i < argc; ++i)
    {
        printf ("argv[%d]: %p\n", i, argv[i]);
    }
    // Print the NULL for good measure
    printf ("argv[%d]: %p\n", i, argv[i]);
    printf ("\n");

    // Print the values of the memory pointed at by argv
    for (i = 0; i < argc; ++i)
    {
        print_memory(argv[i]);
    }

    return 0;
}

Пример прогона:

$ ./a.out Hello World!
argv: ffbfefd4

argv[0]: ffbff12c
argv[1]: ffbff134
argv[2]: ffbff13a
argv[3]: 0

ffbff12c: .
ffbff12d: /
ffbff12e: a
ffbff12f: .
ffbff130: o
ffbff131: u
ffbff132: t
ffbff133:
ffbff134: H
ffbff135: e
ffbff136: l
ffbff137: l
ffbff138: o
ffbff139:
ffbff13a: W
ffbff13b: o
ffbff13c: r
ffbff13d: l
ffbff13e: d
ffbff13f: !
ffbff140:

$

У вас есть этот большой непрерывный массив от ffbff12c до ffbff140, который содержит аргументы командной строки (это не гарантирует, что он будет соответствовать стандарту, но как это обычно делается). argv просто содержит указатели в этом массиве, поэтому вы знаете, где искать слова.

argv - указатель... на указатели... на символы