我正在试验使用_Generic来制作一个线程安全的strerror函数,它不知道使用strerror_r的XSI或GNU变体。XSI变体返回一个int并修改传入它的缓冲区的内容,而GNU则返回一个char *。
strerror.c
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "strerror.h"
static inline char *strerror_r_gnu(int errnum, char *buf, size_t buflen);
static inline char *strerror_r_xsi(int errnum, char *buf, size_t buflen);
static inline char *strerror_r_gnu(int errnum, char *buf, size_t buflen) {
// FUNKY CASTING TO SILENCE COMPILER WARNING BELOW
return (char *)(intptr_t)strerror_r(errnum, buf, buflen);
}
static inline char *strerror_r_xsi(int errnum, char *buf, size_t buflen) {
// Cast result to int to shut up compiler when using GNU strerror()
int err = (int)strerror_r(errnum, buf, buflen);
if (err) {
snprintf(buf, buflen, "%s error", __func__);
// If your buffer can't fit this error message, you deserve truncation
buf[buflen-1] = '\0';
}
return buf;
}
char *strerror_p(int errnum, char *buf, size_t buflen) {
return _Generic(strerror_r,
int (*)(int, char *, size_t) : strerror_r_xsi(errnum, buf, buflen),
char * (*)(int, char *, size_t) : strerror_r_gnu(errnum, buf, buflen)
);
}strerror.h
#ifndef STRERROR_H
#define STRERROR_H
char *strerror_p(int errnum, char *buf, size_t buflen);
#endif // STRERROR_Hmain.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "strerror.h"
int main(void){
const int buflen = 128;
char buf[buflen]; // Flawfinder: ignore
fprintf(stderr, "%s\n", strerror_p(EINVAL, buf, buflen));
return EXIT_SUCCESS;
}在strerror_r_gnu函数中,在不转换strerror_r结果的情况下,编译器在使用XSI版本的strerror_r编译时会发出警告incompatible integer to pointer conversion returning 'int' from a function with result type 'char *'。由于这个函数在编译XSI版本的strerror_r时永远不会被调用,所以我不关心类型不匹配,但是我希望编译器对它保持沉默。转换为intptr_t,然后转换为char *,则会静默编译器警告。
问题是,当使用返回char *的GNU char *进行编译时,是否很好地将结果转换为intptr_t并返回到char *?
发布于 2018-08-09 21:34:27
问题是,当使用返回char *的GNU strerror_r编译时,是否很好地定义了将结果转换为
intptr_t并返回char *?
是。这种操作的安全性在很大程度上是标准中intptr_t的定义:
7.20.1.4能够保存对象指针的整数类型
1.下面的类型指定一个有符号整数类型,该类型的属性是,任何指向void的有效指针都可以转换为此类型,然后再转换回指针为void,结果将与原始指针相比较: intptr_t
(将其与6.2.5p28相结合
指向空的指针应具有与指向字符类型的指针相同的表示和对齐要求。同样,指向兼容类型的合格或非限定版本的指针应具有相同的表示和对齐要求。指向结构类型的所有指针应具有相同的表示和对齐要求。指向联合类型的所有指针应具有相同的表示和对齐要求。指向其他类型的指针不需要有相同的表示或对齐要求。
)
https://stackoverflow.com/questions/51775990
复制相似问题