【问题标题】:How exactly is a pointer to statically allocated structure, returned from a function?从函数返回的指向静态分配结构的指针究竟如何?
【发布时间】:2020-07-25 15:41:06
【问题描述】:

在 Michael Kerrisk 的书中,我遇到过这样的陈述:

  • “gmtime() 和 localtime() 函数将 time_t 值转换为 所谓的故障时间。故障时间放在a
    静态分配的结构,其地址返回为
    函数结果。
  #include <time.h> 
  struct tm *gmtime(const time_t timep );
  struct tm *localtime(const time_t * timep ); 
  /* Both return a pointer to a statically allocated broken-down time structure on
 success, or NULL on error */

所以我试图弄清楚说“指向静态分配结构的指针”是什么意思,并在跟踪 “time.h” 文件的源代码时,我到达了文件 glibc/time/localtime.c 按如下顺序跟踪源时; https://code.woboq.org/userspace/glibc/time/gmtime.c.html

https://code.woboq.org/userspace/glibc/time/localtime.c.html#22

据我了解,gmtime() 函数返回一个指向这个全局定义结构的指针,声明如下:

struct tm _tmbuf;

所以我的问题是,到目前为止我是否正确,gmtime 只返回一个指向这个全局结构的指针?如果是这样,下一个问题是,我是否可以在共享库文件中定义全局变量?如果是,如何访问库文件中的这些全局变量?

【问题讨论】:

  • 是的,你没看错。但是,您的后续行动尚不清楚。是的,您可以在共享库中拥有全局变量,并像访问任何其他全局变量一样访问它。有什么难理解的?
  • “指向静态分配结构的指针”例如Person p = Person_create("John", 35, "Canada"); Person *pp = &amp;p 所以这里的变量pp 是指向静态分配结构的指针

标签: c linux pointers time


【解决方案1】:

是的,你猜对了,是的,你可以做同样的事情。如果您要在自己的库中编写这样的函数,它可能如下所示:

struct tm _tmbuf;

struct tm *gmtime(const time_t *timep)
{
    struct tm *t = &_tmbuf;
    // Do some things with timep and t.
    return t;
}

但是请注意,正如所写,这不是线程安全的。如果您希望人们在线程程序中使用您的库,您需要declare your variable as thread local;使用互斥锁、rwlock 或其他互斥机制;或者提供一个线程安全的版本,比如localtime_r 或gmtime_r,用户可以在其中指定要用作输出的结构。

由于这些原因,通常认为这样做是不可取的,而像 Rust 这样的语言使它变得困难,因为它很容易成为线程不安全的。

【讨论】:

  • 那么当使用 _Thread_local 或 thread_local 进行变量声明时它是否可移植?
  • 并不是它不便携,只是它不是线程安全的。您可以使用这些 C11 线程局部声明中的任何一个,也可以使用编译器提供的声明。
【解决方案2】:

是的,您可以这样做。在示例中使用了一个 char[] 数组,但您也可以使用结构来执行此操作

静态.c:

#include <string.h>

static char my_name[] = __FILE__;

char * get_name(void)
{
return my_name;
}


void set_name(char *newname)
{
size_t len;
if (!newname) return;

len = strlen(newname);
if (len >= sizeof my_name) len =  sizeof my_name -1;

memcpy(my_name, newname, len);
my_name[len] = 0;
}

静态.h:

extern char * get_name(void) ;
extern void set_name(char *newname) ;

staticmain.c:

#include <stdio.h>
#include "static.h"

int main(void)
{
char *name;

name = get_name();
printf("Name=%s\n", name);

set_name( "OMG!");

name = get_name();
printf("Name=%s\n", name);

return 0;
}

编译并链接它们:

$ cc -Wall staticmain.c static.c

运行它:

$ ./a.out
Name=static.c
Name=OMG!
$

在您的情况下,您会将 static.o 对象放入(共享)库中,但机制是相同的

【讨论】:

    猜你喜欢
    • 2022-01-14
    • 2015-02-05
    • 1970-01-01
    • 2016-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多