在C中递增指向多维数组的指针

时间:2016-12-10 11:39:41

标签: c pointers

我有这个小程序:

#include <stdio.h>

int main() {
    char *argv[3] = {{"abc"}, {"def"}, {"ghi"}};

    printf("%c\n", (*++argv)[1]); //error. I wanted to print 'b'
    printf("%c\n", *++argv[1]); //prints e

    return 0;
}

错误消息:

error: cannot increment value of type 'char *[3]'
printf("%c\n", (*++argv)[1]);

我想将argv增加到b。我直接从K&amp; R的C编程语言中使用了这个用法(*++argv)[i],他们在第117页有一个例子,就像我一样递增argv。他们还指出(*++argv)[0]是指向字符串中第一个字符的指针,而*++argv[0]递增指针argv[0]。确实(*argv)[1]将打印b*argv[1]将打印d。然而,以某种方式递增(*++argv)[0]只会导致错误。

3 个答案:

答案 0 :(得分:3)

首先,这个:

char *argv[3] = {{"abc"},{"def"},{"ghi"}};

正如其他人所指出的那样:

char *argv[3] = {"abc", "def", "ghi"};

其次,你所做的并不是K&amp; R书所做的。

数组名称就像它们是常量指针一样,因此您不能像尝试使用argv = argv + 1++argv的扩展版本)那样更改它们。

但是本书通过命令行将argv 传递给main ,所以当char* argv[]进入main时,衰减到指向指针(char**)的指针然后,是的,如果将字符串作为命令行参数传递,则可以使(*++argv)[1]工作。

尝试在main中创建一个伪造的argv,就像你一样,并将其相关地址与传入main via命令行的真实argv相关的地址进行比较。

您会看到一个是char**而另一个是char* array

#include <stdio.h>

int main(int argc, char* argv[]) 
{    
    printf("argv:     %p\n", argv);
    printf("&argv[0]: %p\n", &argv[0]);
    printf("&argv:    %p\n\n", &argv);

    char* bogus_argv[] = {"abc", "def", "ghi"};
    printf("bogus_argv:     %p\n", bogus_argv);
    printf("&bogus_argv[0]: %p\n", &bogus_argv[0]);
    printf("&bogus_argv:    %p\n\n", &bogus_argv);

    printf("%c\n", (*++argv)[1]);  // prints 'b'
    printf("%c\n", *++argv[1]);    // prints 'e'

    return 0;
}

运行:./program abc def ghi

我机器上的输出:

argv:     0x7ffcde5aca98
&argv[0]: 0x7ffcde5aca98
&argv:    0x7ffcde5ac9a0

bogus_argv:     0x7ffcde5ac980
&bogus_argv[0]: 0x7ffcde5ac980
&bogus_argv:    0x7ffcde5ac980

b
e

答案 1 :(得分:2)

来自K&amp; R的示例引用argv定义为函数main的第二个参数。您的定义不同,您定义了一个包含3个字符串指针的数组,而函数参数是指向此类数组的指针

函数原型语法有些误导,因为相同的语法用于不同类型的对象。有些人更喜欢这种语法:

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

使用这个原型,argv(指向char指针的指针)的性质更明确地出现,但许多程序员更喜欢等效的char *argv[]语法来强调argv {1}}指向数组指针而不是单个指针。

argv是您代码中的数组,您无法递增它:这解释了为什么您收到printf("%c\n", (*++argv)[1]);的错误。

您可以通过以下方式更改程序:

#include <stdio.h>

int main(void) {
    char *argument_array[4] = { "abc", "def", "ghi", NULL };
    char **argv = argument_array;

    printf("%c\n", (*++argv)[1]); // will print 'e' instead of 'b'
    printf("%c\n", *++argv[1]);   // prints 'h', not 'e'

    return 0;
}

另请注意,您应该删除初始值设定项中的冗余{},并且++运算符是前缀,因此输出不完全符合您的预期。

答案 2 :(得分:1)

你犯了一个错误的声明。它应该是一个警告。它应该是

char *argv[3] = {"abc","def","ghi"};

内部大括号不是必需的,因为字符串是char指针,因此是“数组”。

您可以声明第二个指针变量并将其分配给argv:

char ** p;
p = argv;

然后增加p。

最后但并非最不重要的是,如果你想先打印b然后再打印e,你必须将“++”运算符放在变量后面。否则它会在评估之前递增指针,你会打印e和h。