【问题标题】:#undef not work as expected in my C program#undef 在我的 C 程序中无法按预期工作
【发布时间】:2018-08-21 10:55:40
【问题描述】:

我正在编写线性列表 ADT 作为我在 DS 课上的练习。我使用一个头文件,一个函数源代码和一个驱动程序作为一个整体项目。我在头文件中定义了宏“ELEMENT_TYPE”和“MAXSIZE”。我的设计是我可以在驱动程序中#undef 并立即#define 这两个宏来将“ELEMENT_TYPE”更改为驱动程序需要的任何类型。 如果我把这些代码:

#undef ELEMENT_TYPE
#define ELEMENT_TYPE char
#undef MAXSIZE
#define MAXSIZE 50

在#define之后插入头文件,然后在驱动程序中,函数可以正确识别(例如,insertion()的第二个扩充是“ELEMENT_TYPE”,使用上面的那些代码,IDE显示插入( ) 在驱动程序中接收一个字符扩充。) 但是,如果我将这些代码放入驱动程序下面的#include "foo.h",那么 IDE 将无法识别函数应该接收什么扩充并使用 "ELEMENT_TYPE" 的初始定义,在这种情况下,诠释。谁知道我的程序出了什么问题,导致预处理指令无法正常工作?

以下是原始代码: 驱动程序.c https://paste.ubuntu.com/p/6B76vmk6nN/

linear_list.c https://paste.ubuntu.com/p/SHq4W5zkGM/

linear_list.h https://paste.ubuntu.com/p/VY8vcgFD89/

PS:我的母语不是英语,所以可能有些地方我没有表达清楚。指出它们,如果需要,我会添加更多详细信息。

【问题讨论】:

  • 欢迎来到 Stack Overflow 请尽快阅读 AboutHow to Ask 页面。如果您的程序是 C,请不要使用 C++ 标签。如果是 C++,请不要使用 C 标签。使用这两种方法会惹恼人们——而被惹恼的人往往会投反对票。您需要在问题中显示您的代码;不接受粘贴箱链接(可能作为备份除外)。阅读有关创建 MCVE (minimal reproducible example) 的信息。
  • 你的编译器是做什么的?它会感到困惑,还是只是您的 IDE?您使用的是哪个 IDE?在哪个平台上?现在您知道人们不一定是 IDE 的粉丝的另一个原因。您也知道 Stroustrup 想要从 C++ 中去掉预处理器的原因。
  • 无法重现:wandbox.org/permlink/8LU7zVOiPLyyTTwY,但请注意警告。

标签: c header-files


【解决方案1】:

源代码中的宏被替换为在源代码中使用宏时生效的宏定义。所以使用ELEMENT_TYPE 的函数声明使用最近在声明之前的宏定义。稍后更改宏不会更改函数定义。

另一种方法是在标题中定义ELEMENT_TYPE,前提是它尚未定义:

#if ! defined ELEMENT_TYPE
    #define ELEMENT_TYPE char
#endif

然后源文件可以执行以下任一操作:

  • 不要定义ELEMENT_TYPE 本身。包含标头时,将使用默认类型char

  • 定义ELEMENT_TYPE,然后包含标题。如果需要,之后可以#undef ELEMENT_TYPE。将使用源文件在ELEMENT_TYPE 中提供的类型。

驱动程序和使用它的程序必须使用相同的类型。您不能使用一种类型编译驱动程序而使用另一种类型编译程序。编译不同类型的程序不会改变驱动。

【讨论】:

    【解决方案2】:

    听起来正在发生的事情是您尝试在驱动程序中 #define 这些值,希望它们将保持在 linear_list.c 中的定义。

    问题是这些文件是分开编译然后链接的。 driver.c 中的#defines 无法更改linear_list.c 中的内容。

    为了获得我认为您想要的效果,您需要在 linear_list.h 中更改这些值。这是执行此操作的最佳方法,因为该标头包含在两个源文件中,并且可能在与 linear_list.c 中定义的函数一起使用的任何文件中为#included。请记住,为了查看程序行为的变化,您不仅需要重新编译 driver.c,还需要在更改 linear_list.h 后重新编译 linear_list.c。

    附带说明一下,您通常应该在 #include stdio.h 和 stdlib.h 等全局头文件之后使用 #include 本地头文件(如 linear_list.h)。在 linear_list.c 中,如果使用了这些标识符,这些标头中的任何一个都可能覆盖您在 linear_list.h 中使用的值。它们看起来可能很常见,某些标头可能会使用它们并不是不可信的,因此将来使用更唯一的标识符可能是值得的。这引出了我的最后一点:在这些标识符上使用 #undef 而不检查它们是否在其他地方使用可能会导致一些问题,因此您通常应该使用 #ifndef 进行检查。

    希望对您有所帮助。如果我误解了,请纠正我。

    编辑:澄清,补充信息,感谢other answer 提醒我一些重要的做法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-24
      • 2015-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多