2014-11-30 3 views
7

КОД 1символ * ARGV [] и полукокса ** ARGV для второго аргумента в главной()

#include<stdio.h> 

int main(int argc, char *argv[]) 
{ 
int j; 
printf("%d", argv[1][0]); 
return 0; 
} 

КОД 2

#include<stdio.h> 

int main(int argc, char **argv) 
{ 
int j; 
printf("%d", argv[1][0]); 
return 0; 
} 

КОД 1 и КОД 2 обе дают такой же мощность. но аргумент 2 основной функции в КОДЕ 1 и КОДЕ 2 различен. Массив указателей создается над секцией данных во время компиляции. argv - массив указателей. Затем мы должны объявить аргумент в главной функции как указатель на указатель на символ, т. Е. ** argv. Как правильно объявить, как в КОДЕ 1?

+6

Второй параметр никоим образом не отличается в отношении компилятора, то есть 'char * argv []' просто эквивалентен 'char ** argv'. Это больше похоже на вопрос предпочтительного стиля кодирования. –

+0

Возможный дубликат [Что должно быть main() в C и C++?] (Http://stackoverflow.com/questions/204476/what-should-main-return-in-c-and-c) –

ответ

7

Основополагающим для c является то, что char** x и char* x[] являются двумя способами выражения то же самое. Оба объявляют, что параметр получает указатель на массив указателей. Напомним, что вы всегда можете написать:

char *parray[100]; 
char **x; 

x = &parray[0]; 

, а затем использовать x тождественно.

+4

Помимо использование 'sizeof' –

+0

@EdHeal достаточно – bmargulies

+0

@EdHeal Пожалуйста, научите больше? –

9

В основном, char * argv [] означает массив указателей на символы, тогда как char ** argv означает указатель на указатель char.

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

Так в приведенном ниже коде в массиве символов x x является указателем на первый элемент, '1', который является символом. Так что это указатель на персонажа.

И в массиве arr, arr является указателем первого элемента x, который сам по себе является указателем на символ. Так что это указатель на другой указатель.

Следовательно, x является char *, а arr является char **.

Принимая что-то в функции, основное правило заключается в том, что вы должны указать тип вещи, которую вы получаете. Поэтому либо вы просто говорите, что хотите получить символ **, либо вы также можете указать char * arr [].

В первом случае нам не нужно думать ни о чем сложном. Мы просто знаем, что мы получаем массив char *. Разве мы не знаем этого? Итак, мы получаем его и используем.

Во втором случае это просто, поскольку я объяснил выше, что arr является символом char **, вы можете поместить это как свой тип и получить его безопасно. Теперь система знает тип материала, который мы получили, мы можем получить доступ к следующим элементам, просто используя аннотацию массива. Это похоже на то, что мы получили начальный адрес массива, мы, безусловно, перейдем к следующим элементам, и, как мы знаем, это тип, мы знаем, что он содержит, и как мы можем использовать это дальше. Мы знаем, что он содержит указатель на char, поэтому мы можем законно обращаться к ним.

void func1(char* arr[]) 
{ 
    //function body 
} 
void func2(char** arr) 
{ 
    //function body 
} 

int main() 
{ 
    //x, y and z are pointer to char 
    char x[3]={'1', '2', '3'}; 
    char y[3]={'4', '5', '6'}; 
    char z[3]={'7', '8', '9'}; 

    //arr is pointer to char pointer 
    char* arr[3]={x, y, z}; 

    func1(arr); 
    func2(arr); 
} 
+2

В этом ответе есть несколько заблуждений, которые уже запутались [по крайней мере, один человек] (https://stackoverflow.com/q/49075372/560648). Во-первых, 'char * argv []' и 'char ** argv' абсолютно эквивалентны и вообще не означают разные вещи. Во-вторых, 'arr' является _not_ указателем. Я не изучил текст достаточно близко, чтобы определить другие конкретные проблемы, но они уже серьезны, чтобы оправдать ниспровержение и искреннюю надежду на то, что вы снова просмотрите этот пост, прежде чем другие будут введены в заблуждение! –

+0

(абсолютно эквивалент _ в этом контексте_, как минимум) –

+0

@LightnessRacesinOrbit Re: [Во-вторых, 'arr' не является указателем] (https://stackoverflow.com/questions/27213580/difference-between-char-argv-and- char-argv-for-the-second-argument-to-main/27213637 # comment85157025_27214187) - возможно, комментируйте, что такое 'arr', а какая' arr' - я вижу различные варианты использования этого ответа. – chux

4

Они точно такие же. §5.1.2.2.2 стандартных состояний C11:

The function called at program startup is named main . The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:

int main(void) { /* ... */ } 

or with two parameters (referred to here as argc and argv , though any names may be used, as they are local to the function in which they are declared):

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

or equivalent;10) or in some other implementation-defined manner.

10) Thus, int can be replaced by a typedef name defined as int , or the type of argv can be written as char ** argv , and so on.

Очевидно, что намерение состоит в том, чтобы оба заявления могут быть одинаковыми. Кроме того, правило описано в п. 6.7.6.3/7:

A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. ...

2

объявить массив как этот

char array[] 

делает его сопзЬ, что означает, что вы не можете иметь следующий код

char array[] = "hello"; 
array = "hey"; 

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

error: array type 'char [6]' is not assignable

если у вас есть **argv вы можете написать

main(int argc, char **argv) 
{ 
    char **other_array; 
    /* 
    * do stuff with other_array 
    */ 
    argv = other_array; 
} 

, если у вас есть *argv[] то

main(int argc, char *argv[]) 
{ 
    char **other_array; 
    /* 
    * do stuff with other_array 
    */ 
    argv = other_array; 
} 

дает вам это предупреждение

warning: assigning to 'const char **' from 'char **' discards qualifiers in nested pointer types

так технически небольшой оптимизации, как если бы вы были написанное const

Смежные вопросы