【问题标题】:Passing the value of a string array to another function将字符串数组的值传递给另一个函数
【发布时间】:2020-02-19 04:23:36
【问题描述】:

我目前正处于编程的第一年,并且已经使用字符串数组解决了一些代码的问题,但不知道它为什么会起作用。我们还在研究指针,但我想尝试一下数组。

我想从主函数传递一个字符串的值,传递给另一个函数,将它与另一个字符串进行比较。如果两个字符串相等,则打印“equal”,否则打印“not equal”。虽然我已经解决了这个问题,但我对它的工作原理感到困惑:

       char name1[100];
       scanf("%s",name1);
       getname(name1[0]); 

return 0;
}

void getname(char name1[0]){

    printf("Name1 is %s",name1);

    return;
}

如果你以这种方式运行它,它将不会运行该函数并会返回一个垃圾值。但是,如果我改变

getname(name1[0]);

进入

getname(&name1[0]);

它工作得很好,这是为什么呢?其次,在“getname”函数中。因为我必须在函数调用中添加与号/地址,所以有人告诉我,我需要在变量旁边添加一个星号,以避免获取实际地址,而是获取实际值。为什么在

printf("Name1 is %s",name1);

它可以完美地打印字符串而不需要它:

printf("Name1 is %s",*name1);

【问题讨论】:

  • 为了确保我理解,name1 被声明为char name1[100]?你是怎么分配给它的?
  • 我认为您的问题中已经包含所需的信息,但理想情况下,请将您显示的代码部分转换为minimal reproducible example
  • What is array decaying?的可能重复

标签: c


【解决方案1】:

void getname(char name1[0]) 正式表示您将传递一个大小为零的字符数组(旁注:zero size arrays are not allowed in standard C 但编译器有时允许这样做)。

它真正的意思是你要传递一个字符指针,一个char *。大小被忽略。它相当于不那么令人困惑的:void getname(char *name1)

此外,由于您不打算更改函数内部的字符串,您可以将其声明为const char *,并在您尝试更改它时收到警告。

#include <stdio.h>

void getname(const char *name1){
    printf("Name1 is %s",name1);

    return;
}

int main() {
    char name[100] = "foo";
    getname(name);
}

getname(name1[0]); 给您带来垃圾,因为您没有传递指向字符串开头的指针,而是传递了字符串的第一个字符。如果字符串是“Yarrow Hock”,则您尝试传入 Y,这实际上是数字 89。C 将尝试读取内存地址 89 处的内容,这可能是垃圾。

如果你用%p打印name1的内存地址就可以看到这个。

void getname(const char *name1){
    printf("Name1 points to %p\n",name1);
    printf("Name1 is %s\n",name1);

    return;
}

您应该会收到如下警告:

incompatible integer to pointer conversion passing 'char' to parameter of
      type 'const char *'; take the address with & [-Wint-conversion]

这让我们看到了一件非常重要的事情:编译器警告。它们非常重要,默认情况下它们是关闭的。打开它们将为您节省数小时的挠头时间。有一系列令人眼花缭乱的可能警告,它们在编译器之间略有不同。这是我使用 clang 的内容。

-Wall -Wshadow -Wwrite-strings -Wextra -Wconversion -std=c11 -pedantic

您可以在Diagnostic flags in Clang 中阅读这些含义。是的,“-Wall”并不意味着“所有警告”。

一个好的代码编辑器,我推荐Atom,在你编辑时也会给你警告。


getname(&amp;name1[0]); 有效,因为它等同于getname(name1 + 0),它等同于getname(name1)name1[0] 是字符串的第一个字符。 &amp; 获取它的地址,它是字符串的开头,就像 name1 本身一样。 printf 然后打印字符直到遇到空字节。

您可以通过尝试getname(&amp;name1[1]) 看到这一点,或者更直接地使用指针算术作为getname(name1 + 1)。这将传入 name1 中 second 字符的地址。如果name1 = "Yarrow Hock" 它将打印arrow Hock。这是在不改变字符串的情况下跳过前缀的有效技术。

【讨论】:

    猜你喜欢
    • 2021-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-08
    • 1970-01-01
    相关资源
    最近更新 更多