如何在c中不使用全局变量

如何在c中不使用全局变量,c,struct,global-variables,C,Struct,Global Variables,我读过墙上的字迹,避免使用全球语言。这就引出了一个显而易见的问题,如何才能做到最好 很明显,我想用当前的项目来做这件事。目标是让远程PC向已经有stdin阅读器的应用程序发送“击键”。其思想是让现有代码检测到没有挂起的击键,然后检查是否有“udp击键”,如果有,则将其填充,使其看起来像是键盘输入。微创,不需要在其他人的代码中重复安装 因此,我拼凑了一个小型UDP套接字读取器,它使用setup()函数打开并绑定端口,然后在循环中使用一个service()函数,该函数使用非阻塞select()一次,

我读过墙上的字迹,避免使用全球语言。这就引出了一个显而易见的问题,如何才能做到最好

很明显,我想用当前的项目来做这件事。目标是让远程PC向已经有stdin阅读器的应用程序发送“击键”。其思想是让现有代码检测到没有挂起的击键,然后检查是否有“udp击键”,如果有,则将其填充,使其看起来像是键盘输入。微创,不需要在其他人的代码中重复安装

因此,我拼凑了一个小型UDP套接字读取器,它使用
setup()
函数打开并绑定端口,然后在循环中使用一个
service()
函数,该函数使用非阻塞
select()
一次,没有循环,只需检查现在是否有任何内容可读取即可。如果是这样,请从套接字读取数据并对其进行处理,否则返回0

// pseudo c
char c;

setup();
while (1)
{
   c = check_for_keyboard_entry();
   if ( c == 0 )
      c = service();
   handle_keypress( c );
   do_a_bunch_of_other_stuff();
}
显而易见的方法是使用几个全局变量在两个函数之间传输端口、超时、sockaddr等。但是,你应该热爱全球,对吗

那么,在函数之间传输六个或八个变量的首选方式是什么

如果我在
setup()
中使用静态变量,那么
service()
例程是否可以访问它们

我想一个被malloc-ed和传递的结构可以工作。我应该使用
cleanup()
来关闭套接字并释放内存


记住,这是一个C问题。没有C++! 您只需将所有信息打包到
结构中即可。该结构可以对客户端可见,也可以是不透明类型。不透明类型可能是更好的选择,因此可以隐藏复杂类型的数据(封装)

typedef struct {
 port_t port;
 timeout_t timeout;
 sockaddr_t sockaddr;
 etc_t etc;
} my_stuff;
然后通过引用传递:

void Foo(my_stuff*);
我想一个被malloc-ed和传递的结构可以工作。我应该有一个cleanup()来关闭套接字并释放内存


一般来说,结构并不总是需要
malloc
'ed。但是,是的,这可能是一种需要的情况。

`我想一个得到malloc并传递的结构可以工作'-你明白了!请将\0修改为0或'\0',我认为使用全局变量没有任何问题(当许多地方只需要全局变量时)。重要的是不要避免全局变量,但不要给变量一个大于其用途的范围。请注意,您也可以使用function
static
variable。通过这种方式,您可以提供某种“getter”接口,使处理全局变量更容易。@sasha.sochka+1以引起注意!但是,这不是使结构成为一个全局结构吗?或者您是想让
foo()
返回指向
my_stuff
的指针吗?如果是这样,当
foo()
的作用域关闭时,
my_stuff
将如何持续?或者你会在
foo()
中将
my_stuff
设置为静态吗?@WesMiller:你可以将它放在外部范围的堆栈上。因此
int main(){my_stuff;stuff.port=80;…;Foo(&stuff);…;返回0;}
。函数中的静态变量实际上是全局的,并且具有类似的问题。@Wesa)不,结构不需要是全局的。b) 不,这个函数原型只是说明了如何通过引用传递它。原型没有指定/建议参数的存储。c) 实例由调用方(或者调用方的调用方或…)拥有。d) nope-函数本地仍然是全局可变存储。函数本地静态可以减少外部访问,但与文件本地静态没有太大区别。-但看起来Maciej的解释+1导致了这一切的“点击”:)如果使用
typedef struct MY_STUFF\u gus MY_STUFFstruct MY_STUFF_GUTS{…}及其关联代码,而不使内部代码可供外部代码使用。这样做的最大限制是外部代码能够声明指向结构的指针,但不能声明单个实例。相反,它必须调用一个函数来接收一个实例(可能通过
calloc
或其他类似的方式提供)。一个风格说明-不要使用
struct
来收集其他不相关的属性,以免传递多个参数。在这种情况下,将端口、超时、sockaddr等属性以及其他与连接相关的参数收集到单个
struct
类型是有意义的,因为它们都与同一操作相关。但是,如果您有一组不相关的属性,那么最好将它们作为单独的参数传递(并且可能仔细看看您的函数在做什么;将其拆分为几个较小的函数可能是有意义的)。