小编Vil*_*ray的帖子

Printf宽度说明符,用于保持浮点值的精度

是否有printf宽度说明符可以应用于浮点说明符,该说明符会自动将输出格式化为必要的有效位数,以便在重新扫描字符串时,获取原始浮点值?

例如,假设我打印float2小数位数的精度:

float foobar = 0.9375;
printf("%.2f", foobar);    // prints out 0.94
Run Code Online (Sandbox Code Playgroud)

当我扫描输出时0.94,我没有符合标准的保证我将获得原始的0.9375浮点值(在这个例子中,我可能不会).

我想要一种方法告诉printf自动将浮点值打印到必要的有效位数,以确保它可以扫描回传递给的原始值printf.

我可以使用一些宏float.h导出要传递的最大宽度printf,但是是否已经有一个说明符可以自动打印到必要的有效位数 - 或者至少是最大宽度?

c floating-point printf c99 floating-point-precision

84
推荐指数
8
解决办法
21万
查看次数

为什么start_routine for pthread_create返回void*并取无效*

pthread_create看起来像这样的函数头:

int pthread_create(pthread_t * thread, 
                   const pthread_attr_t * attr,
                   void * (*start_routine)(void *), 
                   void *arg);
Run Code Online (Sandbox Code Playgroud)

我理解这一切除了函数指针start_routine的形式void* (*fpointer) (void*),这意味着它接受一个void指针并返回一个void指针.

它所采用的void指针只是一种将参数传递给start_routine的方法,我得到了那个部分,但是我不明白为什么函数返回一个void指针?什么代码甚至会注意到void指针?

c posix pthreads

26
推荐指数
2
解决办法
1万
查看次数

从C`goto`错误处理范例转换到C++异常处理范例

我是一名学习C++的C程序员.在C中,有一个常用的goto习惯用法来处理错误并从函数中干净地退出.我已经读过,在面向对象的程序中,通过try- catchblocks的异常处理是首选,但我在使用C++实现这个范例时遇到了麻烦.

以C中的以下函数为例,它使用了goto错误处理范例:

unsigned foobar(void){
    FILE *fp = fopen("blah.txt", "r");
    if(!fp){
        goto exit_fopen;
    }

    /* the blackbox function performs various
     * operations on, and otherwise modifies,
     * the state of external data structures */
    if(blackbox()){
        goto exit_blackbox;
    }

    const size_t NUM_DATUM = 42;
    unsigned long *data = malloc(NUM_DATUM*sizeof(*data));
    if(!data){
        goto exit_data;
    }

    for(size_t i = 0; i < NUM_DATUM; i++){
        char buffer[256] = "";
        if(!fgets(buffer, sizeof(buffer), fp)){
            goto exit_read;
        }

        data[i] = …
Run Code Online (Sandbox Code Playgroud)

c c++ error-handling exception-handling exception

24
推荐指数
4
解决办法
3201
查看次数

为什么按位运算比旧微处理器上的加/减操作稍快?

我今天看到了这段摘录:

在大多数较旧的微处理器上,按位运算比加法和减法运算稍快,并且通常比乘法和除法运算快得多.在现代体系结构中,情况并非如此:按位运算通常与添加速度相同(尽管仍然比乘法更快).

我很好奇为什么按位操作比旧微处理器上的加/减操作稍快一些.

我能想到的只会导致延迟的是,实现加/减的电路取决于几级逻辑门(并行加法器和诸如此类),而按位运算则具有更简单的电路实现.这是什么原因?

我知道算术和按位运算都在现代处理器的一个时钟内执行,但纯粹谈到电路的传播时间,理论上现在处理器中的延迟仍然存在吗?

最后,我有一个关于按位移位操作执行的概念C问题:

unsigned x = 1;
x <<= 5;

unsigned y = 0;
y += 32;
Run Code Online (Sandbox Code Playgroud)

双方xy应持有的价值32,但它采取5个独立左移获得x该值(中位运算的变化通过管道实现)?为了澄清,我纯粹是在询问电路行为而不是时钟周期数.

c bit-manipulation cpu-architecture bitwise-operators digital-logic

22
推荐指数
1
解决办法
1万
查看次数

相当于Windows中的./configure?

./configure在Windows中相当于什么?

有时我下载一个C/C++库,当我使用make时,它会显示"use ./configure"但显然./configure只能在Linux机器上使用,而且库通常没有在Windows上编译的指令(尽管它们支持Windows) ,他们不提供说明).

例如,库wxSVG表示它可以在Windows上运行,但是当我下载它时,我没有看到任何在Windows上编译的指令,我只有Linux文件用于配置它.

c++ windows compilation

20
推荐指数
2
解决办法
4万
查看次数

使用void*键入punning而不破坏C99中的严格别名规则

我最近遇到了严格的别名规则,但是我无法理解如何在void *不违反规则的情况下执行类型惩罚.

我知道这违反了规则:

int x = 0xDEADBEEF;

short *y = (short *)&x;
*y = 42;

int z = x;
Run Code Online (Sandbox Code Playgroud)

而且我知道我可以安全地使用C99中的联合进行类型惩罚:

union{
    int x;
    short y;
} data;

data.x = 0xDEADBEEF;
data.y = 42;

int z = data.x;
Run Code Online (Sandbox Code Playgroud)

但是如何void *在C99中安全地执行打字?以下是正确的:

int x = 0xDEADBEEF;

void * helper = (void *)&x;

short *y = (short *)helper;
*y = 42;

int z = x;
Run Code Online (Sandbox Code Playgroud)

我怀疑代码仍然会破坏严格的别名规则,因为变量x地址的内存可以由两者修改x并且可以解除引用y.

如果未定义类型 - 惩罚void *,那么void * …

c c99 strict-aliasing void-pointers type-punning

20
推荐指数
1
解决办法
4746
查看次数

如何在Linux内核v3.2中创建一个简单的sysfs类属性

我正在学习如何在我的Linux模块中使用sysfs,但我最难找到有关这些主题的当前文档.我一直在使用的Linux设备驱动程序第3版书似乎在这个领域相当过时(例如,class_device在当前的Linux版本中,结构似乎完全消失了).

我只是试图在我的模块的相应sysfs类下获得一个属性,这将允许我从内核空间读取模块变量的值.

在我的代码中,我创建了一个类,允许udev在/ dev/foo为我的模块创建一个设备节点:

dev_t foo_dev;
alloc_chrdev_region(&foo_dev, 0, 1, "bar");

struct class *bar = class_create(THIS_MODULE, "bar");

device_create(bar, NULL, foo_dev, NULL, "foo");

struct cdev foo_dev_file;
cdev_init(&foo_dev_file, &fops); /* fops defined earlier */
cdev_add(&foo_dev_file, foo_dev, 1);
Run Code Online (Sandbox Code Playgroud)

当我插入模块时,我得到了一个sysfs类目录,并在/ sys/class/bar/foo /中填充了一些默认属性.如何创建显示在此新目录下的属性?

我相信我的概念非常好 - 创建属性结构,定义sysfs_ops函数等 - 我的问题是我不知道使用哪个特定的内核结构(class_attribute?),也不知道如何使这些属性出现在右边sysfs目录.

有人会指点我的教程或文章详细介绍当前Linux内核的过程吗?

c linux linux-device-driver linux-kernel sysfs

18
推荐指数
2
解决办法
3万
查看次数

为什么我能够在Linux内核模块中执行浮点运算?

我正在使用x86 CentOS 6.3(内核v2.6.32)系统.

我将以下函数编译成一个简单的字符驱动程序模块作为实验,以了解Linux内核如何对浮点运算做出反应.

static unsigned floatstuff(void){
    float x = 3.14;
    x *= 2.5;
    return x;
}

...

printk(KERN_INFO "x: %u", x);
Run Code Online (Sandbox Code Playgroud)

编译的代码(这是没有预料到的)所以我插入了模块并检查了日志dmesg.日志显示:x: 7.

这看起来很奇怪; 我以为你不能在Linux内核中执行浮点运算 - 除了一些例外kernel_fpu_begin().模块是如何执行浮点运算的?

这是因为我在x86处理器上吗?

c linux x86 gcc linux-kernel

12
推荐指数
2
解决办法
6874
查看次数

如果传递冲突的编译器标志,GCC如何表现?

我知道如果你执行GCC:

gcc -O3 -O2 foo.c
Run Code Online (Sandbox Code Playgroud)

GCC将使用传递的最后一个优化标志(在本例中O2).但是,这对所有旗帜都是如此吗?例如,如果我像这样执行GCC:

gcc -mno-sse -msse bar.c
Run Code Online (Sandbox Code Playgroud)

它会支持SSE,因为那是传递的最后一个标志,还是会导致未定义的行为?我最初的实验似乎表明它将支持SSE,但我不确定这是否适用于所有情况.

c linux gcc

12
推荐指数
1
解决办法
2580
查看次数

int16_t到int会话可以导致实现定义的行为吗?

在C99标准的第7.18.1.1节第1段中:

typedef名称intN_t指定有符号整数类型,其宽度为N,无填充位和二进制补码表示.

根据C99标准,精确宽度有符号整数类型需要具有二进制补码表示.这意味着,例如,int8_t具有最小值-128而不是1的补码最小值-127.

第6.2.6.2节第2段允许实现决定是将符号位解释为符号和幅度,二进制补码还是一个补码:

如果符号位为1,则应以下列方式之一修改该值:
- 符号位0的相应值被否定(符号和幅度);
- 符号位的值为 - (2 N)(二进制补码);
- 符号位的值为 - (2 N - 1)(1'补码).

方法之间的不同之处很重要,因为二进制补码(-128)中的整数的最小值可能超出了补码(-127to 127)中可表示的值的范围.

假设一个实现将int类型定义为具有ones' complement表示,而int16_t类型具有two's complementC99标准保证的表示.

int16_t foo = -32768;
int bar = foo;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,转换 …

c casting c99 type-conversion language-lawyer

12
推荐指数
1
解决办法
2554
查看次数