小编Jas*_*son的帖子

为什么编译器不再使用严格的别名来优化此UB

谷歌严格别名的第一个结果之一就是这篇文章 http://dbp-consulting.com/tutorials/StrictAliasing.html
我注意到的一个有趣的事情是:http://goo.gl/lPtIa5

uint32_t swaphalves(uint32_t a) {
  uint32_t acopy = a;
  uint16_t* ptr = (uint16_t*)&acopy;
  uint16_t tmp = ptr[0];
  ptr[0] = ptr[1];
  ptr[1] = tmp;
  return acopy;
}
Run Code Online (Sandbox Code Playgroud)

被编译为

swaphalves(unsigned int):
        mov     eax, edi
        ret
Run Code Online (Sandbox Code Playgroud)

由GCC 4.4.7.任何比这更新的编译器(文章中提到的4.4所以文章没有错)都没有实现该功能,因为它可以使用严格别名.这是什么原因?它实际上是GCC中的错误还是GCC决定放弃它,因为许多行代码是以产生UB的方式编写的,或者它只是一个持续多年的编译器回归...而Clang也没有优化它.

c c++ gcc clang strict-aliasing

16
推荐指数
2
解决办法
1054
查看次数

为什么零长度VLA UB?

2011年标准明确规定......

6.7.6.2数组声明符

  1. 如果size是一个不是整数常量表达式的表达式:如果它出现在函数原型范围的声明中,则将其视为替换为 *; 否则,每次评估它时,其值应大于零.可变长度数组类型的每个实例的大小在其生命周期中不会改变.如果size表达式是运算sizeof符操作数的一部分,并且更改size表达式的值不会影响运算符的结果,则无法指定是否计算size表达式.

这是设计,但以下代码似乎是合理的.

size_t vla(const size_t x) {

  size_t a[x];
  size_t y = 0;

  for (size_t i = 0; i < x; i++)
    a[x] = i;

  for (size_t i = 0; i < x; i++)
    y += a[i % 2];

  return y;
}
Run Code Online (Sandbox Code Playgroud)

Clang似乎为它生成合理的x64程序集(没有优化).显然索引零长度VLA没有意义,但访问超出边界会调用未定义的行为.

为什么零长度数组未定义?

c arrays variable-length-array

9
推荐指数
2
解决办法
224
查看次数

从另一个创建一个函数

不仅仅是一般情况,我有一个非常具体的例子:在GSL(GNU科学库)中,使用的主要函数类型(为了执行集成,根查找,...)是gsl_function,它有一个属性function类型是 double(*)(double, void *)

说我想创建一个gsl_functiondouble a_squared(double a) {return a*a};.我a__squared的类型是double(*)(double)我想创建一个convert函数接受参数(double(*)(double) f)并返回一个double(*)(double, void *)满足的类型的对象convert(f)(double a, NULL) == f(a)

但经过一些研究,似乎我无法在我的convert函数中定义另一个函数.如何进行 ?

c c++ gsl

7
推荐指数
1
解决办法
259
查看次数

为什么gcc在按值传递普通结构时会发出不需要的内存访问?

众所周知,一些没有非平凡复制的小结构,没有非平凡的dtor在寄存器中传递.

引用ARM程序调用标准:

大于32位的基本类型可以作为参数传递给函数调用,或者作为函数调用的结果返回.当这些类型在核心寄存器中时,以下规则适用:双字大小类型在两个连续寄存器中传递(例如,r0和r1,或r2和r3).寄存器的内容就好像该值是通过单个LDM指令从存储器表示加载的.

事实上,我可以轻松地用铿锵声证实这一点.然而,gcc为这样一个简单的代码片段发出了大量的内存加载和存储:

struct Trivial {
    int i1;
    int i2;
};

int foo(Trivial t)
{
    return t.i1 + t.i2;
}
Run Code Online (Sandbox Code Playgroud)
$ clang++ arm.cpp -O2 -mabi=aapcs -c -S && cat arm.s

add r0, r0, r1
bx  lr
Run Code Online (Sandbox Code Playgroud)
$ g++ arm.cpp -O2 -mabi=aapcs -c -S && cat arm.s

sub     sp, sp, #8
add     r3, sp, #8
stmdb   r3, {r0, r1}
ldmia   sp, {r0, r3}
add     r0, r0, r3
add     sp, sp, #8
bx      lr
Run Code Online (Sandbox Code Playgroud)

我正在使用由ArchlinuxARM发行版提供的gcc和clang,在raspberry pi 2(gcc 5.2)上运行,但我也用基于gcc的交叉编译器再现它.

c++ assembly arm calling-convention

7
推荐指数
1
解决办法
137
查看次数

如何阻止fprintf在Windows中与\n一起打印到文件

当我使用fprintf:

fprintf(somefile,"%c",'\n');
Run Code Online (Sandbox Code Playgroud)

它将"\ r \n"打印到文件中.我如何打印'\n'?
我正在写一个二进制文件.上面的代码仅用于调试.

c windows printf line-endings

5
推荐指数
1
解决办法
344
查看次数

在Linux中,getrusage(RUSAGE_THREAD,...)和clock_gettime(CLOCK_THREAD_CPUTIME_ID,...)有什么区别?

这个问题几乎说明了一切。根据的手册页getrusage(),它返回:

           struct timeval ru_utime; /* user CPU time used */
           struct timeval ru_stime; /* system CPU time used */
Run Code Online (Sandbox Code Playgroud)

根据的手册页clock_gettime(),它返回:

   CLOCK_THREAD_CPUTIME_ID (since Linux 2.6.12)
          Thread-specific CPU-time clock.
Run Code Online (Sandbox Code Playgroud)

那么,(特定于线程的)“使用的用户/系统CPU时间”与特定于线程的CPU时间时钟有何不同?

显然,我之所以问是因为,在从自定义RTOS移植到Linux的应用程序中,我看到了两者之间的差异。该应用程序具有通过tick()tock()功能实现的内部配置文件功能。我一直在研究这个问题,因此我将应用程序的一部分退化为:

tick()
// code commented out
tock()
Run Code Online (Sandbox Code Playgroud)

tick()函数记录运行时间,tock()函数记录运行时间,计算两者之间的增量,并报告该增量。当我实现tick()tock()使用时getrusage(),我得到的大部分为0,偶尔会有1000us或10000us的值(根据我是否将内核配置为1kHz或100Hz操作)。当我实现tick()tock()使用时clock_gettime(),我得到的值以13us为中心(偶尔会出现75us或100us的奇异偏移,但稍后再讨论)。

我尝试在内核和VIRT_CPU_ACCOUNTINGand / or的各种组合中启用高分辨率计时器VIRT_CPU_ACCOUNTING_GEN。我看到的唯一效果是,报告的非零值getrusage()从1000us更改为以1000us为中心的更高精度的范围。

我最终转而使用clock_gettime()并获得了更可信的结果,但是我想知道为什么这两个系统调用存在,以及为什么它们的行为如此不同。所以我想我应该问一些专家。

linux multithreading real-time

5
推荐指数
1
解决办法
640
查看次数

部分排列

我有以下递归函数输出部分组合:

void comb(string sofar, string rest, int n) {

    string substring;

    if (n == 0)
        cout << sofar << endl;
    else {
        for (size_t i = 0; i < rest.length(); i++) {
            substring = rest.substr(i + 1, rest.length());
            comb(sofar + rest[i], substring, n - 1);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如此称呼:

comb("", "abcde", 3);
Run Code Online (Sandbox Code Playgroud)

通过部分组合,我的意思是它使用n个选项和r个元素(而不是n个选项,n个元素).

但是,我想考虑元素的顺序(即排列).我可以找到很多完全排列的算法,但不是部分的.

c++ permutation

5
推荐指数
2
解决办法
1147
查看次数

C#中允许O(1)反向的数据结构

我有一些列表需要迭代,有时从头到尾,有时从头到尾。此列表从未修改过,我将对其进行多次遍历。当我要从头到尾进行迭代时,我想避免在O(n)中反转列表的操作。

是否有某种允许的数据结构?

我以为C#中的(双重)LinkedList实现允许这种行为很简单(通过保留列表开头的内部引用),但是我不认为它是通过这种方式实现的。如果我错了,可以提供一个链接吗?

c# reverse list data-structures

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

类型转换和相等行为

我是Haskell的新手,只是偶然发现了这个问题.我试图找出解释,但我没有足够的经验与Haskell类型确定.

功能:

mystery :: Int -> Int -> Float -> Bool
mystery x y z = not ((x==y) && ((fromIntegral y) == z ))
Run Code Online (Sandbox Code Playgroud)

表现得像它似乎会.它基本上检查值是否都不相等,但是从a进行类型转换Integral y以确保它可以与之进行比较z

如果这是真的,那么为什么:

case1 = do 
    if mystery 1 1 1.00000001 -- a very small number
        then putStrLn "True"
        else putStrLn "False"
Run Code Online (Sandbox Code Playgroud)

打印错误(即,值全部相等,所以1 == 1 == 1.00000001),而:

case2 = do 
    if mystery 1 1 1.0000001 -- a larger number
        then putStrLn "True"
        else putStrLn "False"
Run Code Online (Sandbox Code Playgroud)

打印真的吗?(即.值并非全部相等)

我知道它可能与精度有关,但我不明白.任何帮助是极大的赞赏.

floating-point precision haskell

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

Linux API 调用以实现 rm、mv 和 cp

我正在用 C 编写我自己的小外壳,或者至少我今天要开始。我想实现三个功能。

  • remove file1

为此我需要哪些系统调用?只需打开文件并删除其内容,或者除了使用之外是否还有删除文件的系统调用rm

  • mycopy source destination

为此,我正在考虑让一个缓冲区并打开 file1 读入缓冲区并写出到 file2 但我不知道如何将它实际放入代码中,如果有人可以将一个小例子放在一起,这对很多人有帮助。

  • move source destination

这只是实现复制和删除吗?

我的主要问题是使用 argv[] 参数我从来没有这样做过,所以它对我来说是新的。

c linux system-calls gnu-coreutils

0
推荐指数
1
解决办法
2874
查看次数