【问题标题】:Void function with a pointer带指针的无效函数
【发布时间】:2021-06-23 14:59:42
【问题描述】:

我正在尝试编写代码来检查 int 指针是否为偶数。
我的代码是这样的:

#include <stdio.h>
#include <string.h>

void isEven (int *isFlag, int num) {
    if (num % 2 == 0) {
        *isFlag = 1;
    } else {
        *isFlag = 0;
    }
}

int main() {
    int num = 4;
    int *isFlag = 0;
    isEven(isFlag, num);
    printf("%d", isFlag);
}  

但是我得到了分段错误,我应该看到isFlag = 1,代码中的问题是什么? (我知道我们可以做得更好,但我正在尝试理解指针)

【问题讨论】:

  • int *isFlag = 0 是你的问题。您应该为 int 分配内存并将其分配给 isFlag。
  • 打开编译器警告并阅读它们。 printf("%d", isFlag); -> printf("%d", *isFlag);。这是问题之一。
  • printf("%d", isFlag) 打印指针的地址。
  • 你用指针写。当你通过它写的时候告诉我那个指针指向的地方,我不必告诉你为什么会有段错误。
  • 正要发布我的答案,然后我看到了 4 个答案,似乎每个人都在赶潮流 ^^ 请注意,您将 isFlag 声明为 ptr,我认为 dbush 的答案最准确地反映了什么你应该这样做,以及其他很好的解释

标签: c pointers null-pointer


【解决方案1】:

int *isFlag = 0;isFlag 定义为指向int 的指针,并将其初始化为指向“无处”。 (当常量0用于指针时,表示空指针,不指向任何对象或函数。)

您不需要在main 例程中为此函数创建指针。您可以使用int isFlag = 0; 定义一个普通的int,并使用isEven(&amp;isFlag, num);int 的地址传递给isEven

&amp;isFlag 将获取isFlag 的地址并将其传递给isEvenisEven 参数int *isFlag 将具有该指针的值。尽管它与main 中的isFlag 同名,但它是一个不同的对象,因为它是在不同的范围内定义的(在函数参数内部而不是main 内部),并且它具有不同的类型;它将是一个指向int 的指针。因此,您将其用作 *isFlag 内的 isEven 来访问它指向的 int

【讨论】:

    【解决方案2】:

    您将 isFlag 声明为 main 中的指针并将其设置为 NULL 指针常量。然后将该 NULL 指针传递给尝试取消引用它的 isEven。取消引用 NULL 指针会触发 undefined behavior,在这种情况下会导致崩溃。

    isFlag 定义为int,并将其地址传递给isEven

    int main() {
        int num = 4;
        int isFlag;
        isEven(&isFlag, num);
        printf("%d", isFlag);
    }  
    

    【讨论】:

      【解决方案3】:

      代码有什么问题?

      在询问我们之前,让您的编译器告诉您它认为您的代码可能存在哪些问题:

      Why should I always enable compiler warnings?

      如果你这样做了,编译器会告诉你(以 gcc 为例):

      <source>: In function 'main':
      <source>:16:14: warning: format '%d' expects argument of type 'int', but argument 2 has
      type 'int *' [-Wformat=]
         16 |     printf("%d", isFlag);
            |             ~^   ~~~~~~
            |              |   |
            |              int int *
            |             %ls
      

      这不是确切为什么您会遇到分段错误,但它确实告诉您您正在将指向 int 的指针视为intprintf() 指令确实如此——但更普遍的是。因此,您对 0 的初始化就是您将如何初始化 int... 正如其他答案所解释的那样,这不是您想要做的。

      【讨论】:

        【解决方案4】:

        您的代码的问题在于您似乎打错了字,因为您还没有关于指针的扎实知识。

        在此声明中

        int *isFlag = 0;
        

        您声明了一个空指针,因为它是由整数常量 0 初始化的。因此使用空指针访问内存会导致未定义的行为。

        另一方面,在此声明中

        printf("%d", isFlag);
        

        您将变量isFlag 输出为int 类型的变量。

        您需要将变量声明为确实具有int 类型,并通过指向它的指针通过引用将其传递给函数。

        这就是main中的代码看起来像

        int main( void ) {
            int num = 4;
            int isFlag = 0;
            isEven( &isFlag, num );
            printf("%d", isFlag);
        }  
        

        还可以更简单地定义函数isEven

        void isEven( int *isFlag, int num ) {
            *isFlag = num % 2 == 0;
        }
        

        【讨论】:

          【解决方案5】:

          大家总结了几个问题。

          如果你仍然想坚持你的例子(你不应该,更喜欢dbush's solution),你仍然可以通过以下方式实现它,将内存分配给ptr:

          #include <stdio.h>
          #include <string.h>
          #include <stdlib.h>
          
          void isEven (int *isFlag, int num) {
              if (num % 2 == 0) {
                  *isFlag = 1;
              } else {
                  *isFlag = 0;
              }
          }
          int main() {
              int num = 4;
              int *isFlag;
          
              isFlag = malloc(sizeof(int));
              isEven(isFlag, num);
              printf("%d\n", *isFlag); // also use *isFlag to print the value at ptr's address
              printf("%p\n", isFlag); // print isFlag's address
          }  
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-05-23
            • 2013-05-21
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多