在C语言中打印数组指针中的值

7

我似乎无法理解一个问题。我错过了什么?

请考虑以下内容

int main(int argc, char *argv[]) {
    while ( *argv ) {
        printf("argv[] is: %s\n", *argv);
        ++argv;
    }

    return 0;
}

这会打印出argv的每个值。所以像./example arg1 arg2这样的命令行将输出以下内容:

`argv[] is: ./example`
`argv[] is: arg1`
`argv[] is: arg2`

现在考虑以下内容(我遇到了麻烦):
int main(void) {
    char *days[] = {
        "Sunday",
        "Monday",
        "Tuesday"
    };
    while ( *days ) {
        printf("day is %s\n", *days);
        *days++;
    }

    return 0;
}

如果我尝试编译,就会出现错误无法增加'type'的值

如果我将*days++更改为(*days)++,它就可以编译。 如果我运行它,它会一直运行并最终失败,出现bus error

但是,它不会遍历所有days[]的值。 我甚至尝试在天数数组中放置一个空指针'\0'"\0",但没有效果。

我错过了什么吗?


http://ideone.com/GM4wIN - BLUEPIXY
看看 ++argv;*days++; 的区别! - alk
4个回答

7
您的代码有几个错误:
  1. 变量 argv 和常量 days 之间存在差异。变量可以更改,而常量数组标签则不能。

  2. 在数组中,终止符 NULL 缺失在数组末尾。

  3. 在这种情况下,*days++; 是没有意义的。这只是一个虚拟的操作,返回 days 的值,然后才会对其进行递增。只需要使用 days++ 即可。

因此,您的代码应该如下所示:
#include <stdio.h>

int main(void) {
    char *days[] = {
        "Sunday",
        "Monday",
        "Tuesday",
        NULL
    };

    // Your style
    char **d = days;
    while ( *d ) {
        printf("day is %s\n", *d);
        d++;
    }

    // Or, more "scholastic" code
    for(const char **d = days; *d; d++)
        printf("day is %s\n", *d);

    return 0;

好的,当我声明 char *days[] 时,我实际上没有创建一个指针,而是创建了一个数组?这就是为什么你不得不把数组放在一个名为 *d 的指针中吗?这样我就可以使用指针算术了? - fizzy drink
是的。如果您想了解详细信息,请使用-S选项构建您的程序,并查看汇编代码。 - olegarch
days是一个变量,而不是常量。有一个规则,即数组变量不能被递增。 - M.M
const char **d = days; 是一个错误,因为从 char **const char ** 没有隐式转换。要使用该代码,您还必须将数组声明为 const char *days[] - M.M

6

argv[] 结构包含一个 null 指针作为最后一项,这就是你的代码能够运行的原因。你可以向你的数据结构中添加一个 null 指针。你还需要认识到 argv 是一个参数(就像一个局部变量),它指向保存命令行参数的内部数据结构。你需要创建一个类似的局部变量来迭代数组。

以下是解决方案:

#include <stdio.h>
int main(void) {
    char *days[] = {"Sunday", "Monday", "Tuesday", 0 };
    char **v = days;

  while (v) {
    printf("day is %s\n", *v);
    v++;
  }

  return 0;
}

好的,为什么有双星号 **v?它是指向指针的指针吗?我还没有在任何示例中看到过 **。 - fizzy drink
1
@fizzydrink:在你的代码中,你有一个函数参数定义char *argv[],它的上下文与char ** argv相同。只需替换它,重新编译并获得启示。 - alk

1

不要试图增加字符指针,你应该循环遍历字符数组中的每个元素。

例如:

char *days[] = {
    "Sunday",
    "Monday",
    "Tuesday"
};
int i;    
for (i = 0; i < 3; i++) 
    printf("day is %s\n", days[i]);

3 可以考虑替换为 sizeof(days) / sizeof(days[0]),或者一个枚举常量 enum { NUM_DAYS = sizeof(days) / sizeof(days[0]) }; 或类似的东西。或者使用一个哨兵 NULL 指针来标记数据的结尾,就像将 argv 传递给 main() 时一样 —— 但请注意,传递给 main() 的参数是冗余的,因为您可以通过迭代 argv(或者您可以省略 argv 结尾处的 NULL 元素)来确定 argc,但具有冗余性更方便。 - Jonathan Leffler

1
  1. days 是一个二维字符数组。虽然数组的名称指向第一个地址,但它不是指针。您不能对数组名称进行指针算术运算。
  2. while ( *days ) 永远不会变成 false。您应该更改逻辑。

在下面的代码中,我保留了大部分您的代码。

 #include <stdio.h>

    int main(void) {
        char *days[] = {
            "Sunday",
            "Monday",
            "Tuesday"
        };

       for(int i=0; i < 3; i++) {
            printf("day is %s\n", (days[i]));
        }

        return 0;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接