初始化:函数与文字
Initialization: Function vs. literal
我注意到,在像 libpthread 这样的库中,会有一些结构可以通过两种方式之一进行分配。例如,一个 pthread_mutex_t
可以通过
静态初始化
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
或动态地通过
pthread_mutex_init(&lock);
但是,除非我遗漏了什么,否则 pthread_mutex_init
函数是多余的。也就是说,我不能做吗
lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
?
pthread_mutex_init()
的声明是:
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
因此您可以通过函数调用向初始化程序提供选定的属性,而您不能通过使用 PTHREAD_MUTEX_INITIALIZER
的赋值。
但是,如果您对默认属性感到满意,那么没有明显的理由说明您不能使用 'compound literal' 赋值符号。
请注意,通过赋值重新初始化它来 'destroy' 以前使用过的互斥量是不明智的。始终使用 pthread_mutex_destroy()
函数来销毁互斥锁。如果您为互斥锁使用局部变量,请确保它始终在变量超出范围之前被销毁。并且不要在使用时销毁互斥量。上面引用的 POSIX 页面涵盖了其中的许多要点。
如果我没记错的话函数声明如下
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
也就是说它有两个参数。
可以为已经存在的互斥调用该函数,并且用户可以指定除默认互斥属性之外的任何可接受的属性。
至于宏PTHREAD_MUTEX_INITIALIZER
则根据描述
In cases where default mutex attributes are appropriate, the macro
PTHREAD_MUTEX_INITIALIZER can be used to initialize mutexes that are
statically allocated. The effect is equivalent to dynamic
initialization by a call to pthread_mutex_init() with parameter attr
specified as NULL, except that no error checks are performed.
That is, couldn't I just do
lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
?
PTHREAD_MUTEX_INITIALIZER
扩展为适合 pthread_mutex_t
类型对象的初始值设定项,在文件范围内声明。这必须采用 brace-enclosed 初始化列表或与 pthread_mutex_t
.
兼容的类型常量的形式
如果它是一个 brace-enclosed 初始化列表 那么在它前面加上 (pthread_mutex_t)
会产生一个 [=12= 类型的复合文字].只要不是数组类型,并且它不直接或间接包含任何 const
成员,C 语言允许这样的赋值。
如果它是与 pthread_mutex_t
兼容的类型的常量,则在其前面加上 (pthread_mutex_t)
形成一个类型转换表达式,它C 语言仅在 pthread_mutex_t
为 void 或标量类型时才允许。此类别中的一个合理可能的替代方案是 pthread_mutex_t
是结构类型并且 PTHREAD_MUTEX_INITIALIZER
扩展为复合文字,并且在这种情况下转换将违反语言约束。
那么,从 C-language 的角度来看,假设您可以执行这样的任务是不安全的。
从POSIX的角度来看,规范没有指定PTHREAD_MUTEX_INITIALIZER
的扩展形式,也没有指定它适合您描述的用途。 POSIX-conforming 因此,C 实现可以自由地使用他们希望的任何类型的 built-in 或 special-casing 来实现它,并且除了将其用作初始化程序之外,不需要正确处理任何情况。
从这两个角度来看,不,按照你描述的那样做是不安全的。
此外,正如其他答案所观察到的,初始化宏仅适用于您对默认互斥锁属性感到满意的情况。如果你想要 non-default 属性,比如一个健壮的或 process-shared 互斥锁,那么你必须使用 pthread_mutex_init()
来获得它们。尽管如此,那么,不,pthread_mutex_init()
并不是多余的。
我注意到,在像 libpthread 这样的库中,会有一些结构可以通过两种方式之一进行分配。例如,一个 pthread_mutex_t
可以通过
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
或动态地通过
pthread_mutex_init(&lock);
但是,除非我遗漏了什么,否则 pthread_mutex_init
函数是多余的。也就是说,我不能做吗
lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
?
pthread_mutex_init()
的声明是:
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
因此您可以通过函数调用向初始化程序提供选定的属性,而您不能通过使用 PTHREAD_MUTEX_INITIALIZER
的赋值。
但是,如果您对默认属性感到满意,那么没有明显的理由说明您不能使用 'compound literal' 赋值符号。
请注意,通过赋值重新初始化它来 'destroy' 以前使用过的互斥量是不明智的。始终使用 pthread_mutex_destroy()
函数来销毁互斥锁。如果您为互斥锁使用局部变量,请确保它始终在变量超出范围之前被销毁。并且不要在使用时销毁互斥量。上面引用的 POSIX 页面涵盖了其中的许多要点。
如果我没记错的话函数声明如下
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
也就是说它有两个参数。
可以为已经存在的互斥调用该函数,并且用户可以指定除默认互斥属性之外的任何可接受的属性。
至于宏PTHREAD_MUTEX_INITIALIZER
则根据描述
In cases where default mutex attributes are appropriate, the macro PTHREAD_MUTEX_INITIALIZER can be used to initialize mutexes that are statically allocated. The effect is equivalent to dynamic initialization by a call to pthread_mutex_init() with parameter attr specified as NULL, except that no error checks are performed.
That is, couldn't I just do
lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
?
PTHREAD_MUTEX_INITIALIZER
扩展为适合 pthread_mutex_t
类型对象的初始值设定项,在文件范围内声明。这必须采用 brace-enclosed 初始化列表或与 pthread_mutex_t
.
如果它是一个 brace-enclosed 初始化列表 那么在它前面加上
(pthread_mutex_t)
会产生一个 [=12= 类型的复合文字].只要不是数组类型,并且它不直接或间接包含任何const
成员,C 语言允许这样的赋值。如果它是与
pthread_mutex_t
兼容的类型的常量,则在其前面加上(pthread_mutex_t)
形成一个类型转换表达式,它C 语言仅在pthread_mutex_t
为 void 或标量类型时才允许。此类别中的一个合理可能的替代方案是pthread_mutex_t
是结构类型并且PTHREAD_MUTEX_INITIALIZER
扩展为复合文字,并且在这种情况下转换将违反语言约束。
那么,从 C-language 的角度来看,假设您可以执行这样的任务是不安全的。
从POSIX的角度来看,规范没有指定PTHREAD_MUTEX_INITIALIZER
的扩展形式,也没有指定它适合您描述的用途。 POSIX-conforming 因此,C 实现可以自由地使用他们希望的任何类型的 built-in 或 special-casing 来实现它,并且除了将其用作初始化程序之外,不需要正确处理任何情况。
从这两个角度来看,不,按照你描述的那样做是不安全的。
此外,正如其他答案所观察到的,初始化宏仅适用于您对默认互斥锁属性感到满意的情况。如果你想要 non-default 属性,比如一个健壮的或 process-shared 互斥锁,那么你必须使用 pthread_mutex_init()
来获得它们。尽管如此,那么,不,pthread_mutex_init()
并不是多余的。