javascript

java

python

c#

android

c++

node.js

php

reactjs

jquery

html

css

ios

.net

git

ruby-on-rails

sql

c

string

ruby

这两个高阶函数定义之间有区别吗?

main的4条语句之间有什么区别吗?我觉得只有apply2(&func)才有意义。 但是,所有4个返回相同的值。

int func(void) 
{
    return 1;
}

int apply1( int f1(void) )
{
    return f1();
}

int apply2( int (*f1) (void) ) 
{
    return f1();
}

int main() 
{
    apply1(func); 
    apply1(&func);
    apply2(func);
    apply2(&func);

    return 0;
}
trans by 2020-07-13T13:43:19Z

C Int和Long 32-64位的值范围

我对C中Int变量的值范围感到困惑。

我知道32位无符号整数的范围是:0到65,535。这么久有0到4,294,967,295

这在32bits机器中很好。 但是现在在64位计算机中,所有事物都保持不变吗?也许我的int能力不同?

我将这个问题理解为新手,但我真的很困惑。此方法签名也无济于事。 :)

unsigned long long int atomicAdd(unsigned long long int* address, unsigned long long int val);
trans by 2020-07-13T10:22:04Z

如何在基于Linux的系统上的c程序中使用mqueue?

如何在基于Linux的系统上的c程序中使用mqueue(消息队列)?

我正在寻找一些好的代码示例,这些示例可以显示如何以正确和适当的方式(可能是方法)来完成此操作。

trans by 2020-07-13T04:21:29Z

c-xmalloc和malloc有什么区别?

xmalloc()malloc()之间的内存分配有什么区别?
有使用xmalloc()的专业人士吗?

trans by 2020-07-13T02:38:39Z

C / C ++:如何使用do-while(0); 构造没有C4127之类的编译器警告?

由于此答案中所述的原因,我经常在#defines中使用do-while(0)构造。 另外,我尝试使用编译器提供的尽可能高的警告级别,以捕获更多潜在的问题,并使我的代码更健壮和跨平台。 所以我通常在gcc上使用-Wall,在MSVC上使用/Wall

不幸的是,MSVC抱怨do-while(0)构造:

foo.c(36) : warning C4127: conditional expression is constant

我应该如何处理此警告?

只是全局禁用所有文件? 对我来说,这似乎不是一个好主意。

trans by 2020-07-13T02:26:28Z

字符串终止-char c = 0 vs char c ='\ 0'

在我终止字符串时,在我看来,'\0'在逻辑上等效于'\0',因为“空”(ASCII 0)字节为0,但通常人们会改而选择0。 这是纯粹出于偏爱还是应该成为更好的“实践”?

什么是首选?


编辑:K&R说:“字符常量'\0'表示值为零的字符,空字符。通常写'\0'而不是0来强调某些表达式的字符性质,但数值仅为0

trans by 2020-07-12T23:29:08Z

c-如果我在切换情况下不写默认值怎么办?

int a = 10;
switch(a){
case 0:
    printf("case 0");
    break;
case 1:
    printf("case 1");
    break;
}

以上代码有效吗?

如果我确定int a的值不会是1和0,那么可以避免default吗?

如果在任何情况下值都不同于1和0怎么办?

我知道这是一个愚蠢的问题,但我当时想这可能是非法的或未定义的行为,因此我只是想确认一下。

trans by 2020-07-12T22:07:07Z

c-数组索引在C中越界

为什么在数组索引超出范围的情况下sizeof(a)会有所区别

#include <stdio.h>
int main()
{
    int a[10];
    a[3]=4;
    a[11]=3;//does not give segmentation fault
    a[25]=4;//does not give segmentation fault
    a[20000]=3; //gives segmentation fault
    return 0;
}

我了解到,在sizeof(a)a[25]的情况下,它试图访问分配给进程或线程的内存,而在2963513659726758958914的情况下,它超出堆栈范围。

为什么编译器或链接器没有给出错误,它们是否不知道数组的大小? 如果不是,那么sizeof(a)如何正常工作?

trans by 2020-07-12T18:01:33Z

c-指定-g时,gcc是否定义任何内容?

不久,我想知道是否启用了NDEBUG,gcc(或g ++。我在C中需要它,但对c ++也很好奇)是否定义了任何特殊符号。 可以? 如果是这样,什么符号?

在搜索过程中,我发现:

  • NDEBUG是手动定义的(我的意思是-g)是Visual C程序员的习惯(因为VC在调试模式下编译时定义了_DEBUG
  • 如果未处于调试模式,则定义NDEBUG。 尽管我发现有很多地方在说这句话,但我还是在.c和.cpp文件中尝试了我的gcc和g ++,在没有或没有-g的情况下,都没有定义这样的符号!

编辑:让我演示为什么我不想使用非标准符号:

想象一下,一个内核模块可以执行某些操作,并且还提供要包含在其他内核模块中的头文件,以便它们可以连接到该模块。

现在,作为一种工具,我在一个头文件中拥有:

#ifdef DEBUG <-- This is what I need
#define LOG(x, ...) printk("Some extra info"x, ##__VA_ARGS__);
#else
#define LOG(x, ...) printk("Without extra info"x, ##__VA_ARGS__);
#endif

请注意,名称实际上不是NDEBUG,这是一个示例。

现在,我可以自己为NDEBUG使用任何符号,但是如果有人包含我的标题,则他们可能无法定义该符号。 当然,我可以告诉他们“顺便说一句,以在调试模式下获取标头,定义另一个符号”,但这听起来不对。

我可以在头文件中定义符号,并将其包括在所有头文件中。 这样,如果它们包括我的头文件之一,它们也将获得调试符号。 现在的问题是,如果他们不想在调试模式下进行编译,我的标头仍会认为它们处于调试模式。

因此,我认为最好是使用在使用NDEBUG时定义的符号(如果有)!

更新资料

到目前为止,我得出的结论是我可以执行以下操作:

how_to_build.h

#if !defined(NDEBUG)
#define MY_DEBUG
#endif

用法:

#include "how_to_build.h"

#ifdef MY_DEBUG
// rest of the story

这样,NDEBUG的通用选项也删除了我的定义。 如果他们不希望在调试模式下获取标头,仍然需要我告诉他们定义它。

trans by 2020-07-12T10:25:23Z

c-具有恒定整数除数的有效浮点除法

最近的一个问题,即是否允许编译器用浮点乘法代替浮点除法,启发了我提出这个问题。

在严格的要求下,代码转换后的结果应与实际的除法运算按位相同,显而易见,对于二进制IEEE-754算术,除数为2的幂是可能的。 只要互惠除数的乘积可表示,乘以除数的倒数可得出与除法相同的结果。 例如,乘以x可以替换除以y

然后,一个人想知道这样的除法运算还有其他除数,假设我们允许任何简短的指令序列来代替除法运算,但运行速度明显加快,同时又能产生位相同的结果。 特别是除了普通乘法之外,还允许融合乘法加法运算。在评论中,我指出了以下相关论文:

Nicolas Brisebarre,Jean-Michel Muller和Saurabh Kumar Raina。 预先知道除数时,可以加速正确舍入的浮点除法。 IEEE计算机事务,卷。 53,2004年8月,第8卷,第1069-1072页。

本文作者提倡的技术将除数y的倒数预先计算为归一化的头尾对zh:zl,如下所示:zh = 1 / y,zl = fma(-y,zh,1)/ y。 然后,除法q = x / y然后计算为q = fma(zh,x,zl * x)。 本文推导了除数y才能使该算法起作用的各种条件。 正如人们容易观察到的那样,当头尾符号不同时,该算法存在无限性和零的问题。 更重要的是,由于商尾zl * x的计算会出现下溢,因此对于数量非常小的分红x,它将无法提供正确的结果。

本文还为Peter Markstein在IBM任职时提出的基于FMA的替代除法算法提供了参考。 相关参考是:

P. W. Markstein。 IBM RISC System / 6000处理器上的基本功能的计算。 IBM研究与发展杂志,第1卷。 1990年1月34日第1期,第111-119页

在马克斯坦算法中,首先计算一个倒数rc,由此形成初始商q = x * rc。 然后,使用FMA准确地计算除法的余数,即r = fma(-y,q,x),最后将改进的更精确的商计算为q = fma(r,rc,q)。

该算法还存在x为零或无穷大的问题(可以通过适当的条件执行轻松解决),但是使用IEEE-754单精度2962651399022183483424数据进行的详尽测试表明,它对所有除数y的所有可能性红利x均提供了正确的商 ,其中有许多小整数。 此C代码实现了它:

/* precompute reciprocal */
rc = 1.0f / y;

/* compute quotient q=x/y */
q = x * rc;
if ((x != 0) && (!isinf(x))) {
    r = fmaf (-y, q, x);
    q = fmaf (r, rc, q);
}

在大多数处理器体系结构上,这应该使用谓词,条件移动或选择类型的指令转换为无分支指令序列。 举一个具体的例子:为了除以29626513990221834834,CUDA 7.5的y编译器为开普勒级GPU生成以下机器代码:

    LDG.E R5, [R2];                        // load x
    FSETP.NEU.AND P0, PT, |R5|, +INF , PT; // pred0 = fabsf(x) != INF
    FMUL32I R2, R5, 0.3333333432674408;    // q = x * (1.0f/3.0f)
    FSETP.NEU.AND P0, PT, R5, RZ, P0;      // pred0 = (x != 0.0f) && (fabsf(x) != INF)
    FMA R5, R2, -3, R5;                    // r = fmaf (q, -3.0f, x);
    MOV R4, R2                             // q
@P0 FFMA R4, R5, c[0x2][0x0], R2;          // if (pred0) q = fmaf (r, (1.0f/3.0f), q)
    ST.E [R6], R4;                         // store q

对于我的实验,我编写了下面显示的微型C测试程序,该程序以递增的顺序逐步通过整数除数,并且对于每个除数,都针对适当的除法详尽测试了上述代码序列。 它打印通过此详尽测试的除数的列表。 部分输出如下所示:

PASS: 1, 2, 3, 4, 5, 7, 8, 9, 11, 13, 15, 16, 17, 19, 21, 23, 25, 27, 29, 31, 32, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 64, 65, 67, 69,

为了将替换算法作为优化合并到编译器中,可以安全地应用上述代码转换的除数白名单是不切实际的。 到目前为止,该程序的输出(每分钟大约一个结果的速率)表明,对于那些除数为2962651399022183483425的奇数整数或为2的幂的整数,快速代码可以在所有x的可能编码中正确工作。 传闻证据当然不是证据。

哪些数学条件集可以先验地确定将除法转换为上述代码序列是否安全? 答案可以假定所有浮点运算都是在默认舍入模式“四舍五入到最接近或偶数”下执行的。

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

int main (void)
{
    float r, q, x, y, rc;
    volatile union {
        float f;
        unsigned int i;
    } arg, res, ref;
    int err;

    y = 1.0f;
    printf ("PASS: ");
    while (1) {
        /* precompute reciprocal */
        rc = 1.0f / y;

        arg.i = 0x80000000;
        err = 0;
        do {
            /* do the division, fast */
            x = arg.f;
            q = x * rc;
            if ((x != 0) && (!isinf(x))) {
                r = fmaf (-y, q, x);
                q = fmaf (r, rc, q);
            }
            res.f = q;
            /* compute the reference, slowly */
            ref.f = x / y;

            if (res.i != ref.i) {
                err = 1;
                break;
            }
            arg.i--;
        } while (arg.i != 0x80000000);

        if (!err) printf ("%g, ", y);
        y += 1.0f;
    }
    return EXIT_SUCCESS;
}
trans by 2020-07-12T03:45:48Z

c-gcc标准标头中的括号太多

为什么GCC头文件中的常量表达式用括号括起来呢?

#define INTMAX_MIN (-9223372036854775807LL)
#define INTMAX_MAX (9223372036854775807LL)

如果我这样省略括号,会有什么区别?

#define INTMAX_MIN -9223372036854775807LL
#define INTMAX_MAX 9223372036854775807LL

为什么会有“ L”后缀? 如果我写以下内容,会是一样的吗?

#define INTMAX_MIN -9223372036854775807
#define INTMAX_MAX 9223372036854775807

有实际的用途还是总是一回事?

我知道'L'代表了很长时间,而且我也很清楚C宏中括号的重要性。 我是出于好奇而问这个。

trans by 2020-07-11T22:02:33Z

为什么使用数组大小1而不是指针?

在一个C ++开源项目中,我看到了这一点。

struct SomeClass {
  ...
  size_t data_length;
  char data[1];
  ...
}

这样做比使用指针有什么好处?

struct SomeClass {
  ...
  size_t data_length;
  char* data;
  ...
}

我唯一能想到的就是使用大小为1的阵列版本,预计用户不会看到NULL。 还有别的事吗?

trans by 2020-07-11T20:33:56Z

在C和C ++中静态,自动,全局和局部变量之间的区别

我对localautogloballocal变量有些困惑。

我读到某个地方,只能在函数内访问local变量,但是在函数返回后它们仍然存在(保留在内存中)。

但是,我也知道local变量也一样,所以有什么区别?

trans by 2020-07-11T16:54:37Z

c-sizeof与字符的混淆行为

这个问题已经在这里有了答案:

  • 为什么C字符文字是整型而不是char? 12个答案
#include <stdio.h>
#include <string.h>

int main(void)
{
    char ch='a';

    printf("sizeof(ch)          = %d\n", sizeof(ch));
    printf("sizeof('a')         = %d\n", sizeof('a'));
    printf("sizeof('a'+'b'+'C') = %d\n", sizeof('a'+'b'+'C'));
    printf("sizeof(\"a\")       = %d\n", sizeof("a"));
}

该程序使用sizeof计算尺寸。 为什么'a'的大小与ch(其中ch='a')的大小不同?

sizeof(ch)          = 1
sizeof('a')         = 4
sizeof('a'+'b'+'C') = 4
sizeof("a")         = 2
trans by 2020-07-11T15:20:13Z

c-getc()vs fgetc()-主要区别是什么?

我到处都看到“几乎相同”或类似的东西...

从GNU C编程教程:

GNU C库中还有另一个函数fgetc。 在大多数方面,它与getc相同,除了getc通常是作为宏函数实现且经过高度优化的,因此在大多数情况下是首选。 (在您从标准输入中读取信息的情况下,getc的速度与fgetc差不多,因为与计算机能够读取输入内容的速度相比,人类输入速度较慢,但是当您从非人类交互产生的流中进行读取时, fgetc可能更好。)

其他区别是什么? 我听说它们每个都有不同的实现(并且可以用作宏),但是,是什么让它们在标准C库(或规范)中如此不同(或足够不同)呢?

trans by 2020-07-11T14:09:44Z

c-取消引用类型标记的指针将破坏严格的别名规则

我使用以下代码作为一个较大程序的一部分从文件中读取数据。

double data_read(FILE *stream,int code) {
        char data[8];
        switch(code) {
        case 0x08:
            return (unsigned char)fgetc(stream);
        case 0x09:
            return (signed char)fgetc(stream);
        case 0x0b:
            data[1] = fgetc(stream);
            data[0] = fgetc(stream);
            return *(short*)data;
        case 0x0c:
            for(int i=3;i>=0;i--)
                data[i] = fgetc(stream);
            return *(int*)data;
        case 0x0d:
            for(int i=3;i>=0;i--)
                data[i] = fgetc(stream);
            return *(float*)data;
        case 0x0e:
            for(int i=7;i>=0;i--)
                data[i] = fgetc(stream);
            return *(double*)data;
        }
        die("data read failed");
        return 1;
    }

现在,我被告知使用-O2,并且收到以下gcc警告:warning: dereferencing type-punned pointer will break strict-aliasing rules

谷歌搜索我发现了两个正交的答案:

  • 结论:无需担心; 海湾合作委员会试图比实际法律。

  • 因此,基本上,如果您有一个int *和一个float *,则不允许它们指向相同的内存位置。 如果您的代码不遵守此规定,则编译器的优化器很可能会破坏您的代码。

最后,我不想忽略这些警告。 你会推荐什么?

[更新]我用真实功能替换了玩具示例。

trans by 2020-07-11T10:17:50Z

c-链式哈希表与开放式哈希表

有人可以解释这两种实现之间(优缺点)的主要区别吗?

对于库,建议采用哪种实现?

trans by 2020-07-11T02:02:03Z

c-为什么我的编译防护程序不能防止多个定义包含?

我有一个头文件x.h,其中包含多个* .c源文件。该头文件定义了一些结构变量。

我在头文件的开头放置了多个防止包含的防护措施,如下所示:

#ifndef X_H
#define X_H
...
..
//header file declarations and definitons.


#endif//X_H

在构建过程中,我得到与多个定义有关的链接器错误。 我了解这个问题。

  1. 是否不会像我一样在头文件的顶部使用防止多重包含的防护措施,防止头文件x.h的多重包含,从而避免对x.h中存在的变量进行多次定义?

  2. #pragma曾经无法在此特定编译器上运行,那么解决方案是什么?有人将这个答案发布到了类似的问题上。 它似乎对我不起作用。 这个解决方案如何运作?

trans by 2020-07-11T00:13:42Z

c-如何使用gcc打印__uint128_t数字?

是否存在uint128_t,其行为类似于<inttypes.h>中的__uint128_t

printf("%" PRIu64 "\n", some_uint64_value);

或逐位手动转换:

int print_uint128(uint128_t n) {
  if (n == 0)  return printf("0\n");

  char str[40] = {0}; // log10(1 << 128) + '\0'
  char *s = str + sizeof(str) - 1; // start at the end
  while (n != 0) {
    if (s == str) return -1; // never happens

    *--s = "0123456789"[n % 10]; // save last digit
    n /= 10;                     // drop it
  }
  return printf("%s\n", s);
}

是唯一的选择吗?

请注意,uint128_t是我自己对__uint128_t的typedef。

trans by 2020-07-10T17:50:15Z

c-堆栈分配,填充和对齐

我一直在尝试更深入地了解编译器如何生成机器代码,更具体地说是GCC如何处理堆栈。 为此,我一直在编写简单的C程序,将它们编译为汇编程序,并尽力了解结果。 这是一个简单的程序及其生成的输出:

ESP:

void main() {
    char buffer[5];
}

ESP:

pushl   %ebp
movl    %esp, %ebp
subl    $24, %esp
leave
ret

让我感到困惑的是为什么为堆栈分配了24个字节。 我知道由于处理器如何处理内存,必须以4为增量分配堆栈,但是如果是这种情况,我们应该只将堆栈指针移动8个字节,而不是24个字节。作为参考,缓冲区为17 字节产生的堆栈指针移动了40个字节,堆栈指针8完全没有缓冲区。缓冲区在1到16字节之间(包括1和16字节)移动了ESP 24字节。

现在假设8个字节是一个必要的常量(它需要什么?),这意味着我们将以16个字节的块进行分配。 为什么编译器会以这种方式对齐? 我正在使用x86_64处理器,但是即使是64位字也只需要8字节对齐。 为什么会有差异?

作为参考,我将在运行10.5,gcc 4.0.1且未启用优化的Mac上进行编译。

trans by 2020-07-10T13:43:57Z

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 下一页 共98页