相关疑难解决方法(0)

508
推荐指数
8
解决办法
5万
查看次数

为什么memcmp(a,b,4)有时只针对uint32比较进行优化?

鉴于此代码:

#include <string.h>

int equal4(const char* a, const char* b)
{
    return memcmp(a, b, 4) == 0;
}

int less4(const char* a, const char* b)
{
    return memcmp(a, b, 4) < 0;
}
Run Code Online (Sandbox Code Playgroud)

x86_64上的GCC 7引入了第一种情况的优化(Clang已经做了很长时间):

    mov     eax, DWORD PTR [rsi]
    cmp     DWORD PTR [rdi], eax
    sete    al
    movzx   eax, al
Run Code Online (Sandbox Code Playgroud)

但第二种情况仍然是memcmp():

    sub     rsp, 8
    mov     edx, 4
    call    memcmp
    add     rsp, 8
    shr     eax, 31
Run Code Online (Sandbox Code Playgroud)

是否可以对第二种情况应用类似的优化?什么是最好的装配,有没有明确的理由为什么它没有完成(由GCC或Clang)?

在Godbolt的Compiler Explorer上看到它:https://godbolt.org/g/jv8fcf

c gcc x86-64 clang compiler-optimization

68
推荐指数
3
解决办法
3930
查看次数

memset编写的对象的有效类型是什么?

代码1:

unsigned int *p = malloc(sizeof *p);
memset(p, 0x55, sizeof *p);

unsigned int u = *p;
Run Code Online (Sandbox Code Playgroud)

代码2:

void *d = malloc(50);
*(double *)d = 1.23;
memset(d, 0x55, 50);

unsigned int u = *(unsigned int *)d;
Run Code Online (Sandbox Code Playgroud)

在每种情况下,memset对malloc空间中对象的有效类型有什么影响; 那么初始化u正确还是严格的别名违规?

有效类型的定义(C11 6.5/6)是:

用于访问其存储值的对象的有效类型是对象的声明类型(如果有).如果通过具有非字符类型的左值的值将值存储到没有声明类型的对象中,则左值的类型将成为该访问的对象的有效类型以及不修改该值的后续访问的有效类型储值.如果使用memcpy或将值复制到没有声明类型的对象中memmove,或者将其复制为字符类型数组,则该访问的修改对象的有效类型以及不修改该值的后续访问的有效类型是有效类型复制值的对象,如果有的话.对于没有声明类型的对象的所有其他访问,对象的有效类型只是用于访问的左值的类型.

然而,目前还不清楚是否memset表现得像通过字符类型的左值或其他东西写作.memset(7.24.6.1)的描述并不是很有启发性:

memset函数将c的值(转换为a unsigned char)复制到s指向的对象的前n个字符中.

c strict-aliasing language-lawyer

23
推荐指数
1
解决办法
717
查看次数

将C字节序和指针黑魔法移植到Swift

我正在尝试翻译此代码段:

ntohs(*(UInt16*)VALUE) / 4.0
Run Code Online (Sandbox Code Playgroud)

和其他一些看起来相似的,从C到斯威夫特.问题是,我对Swift知之甚少,我无法理解这个片段的作用......以下是我所知道的全部内容:

  • ntohs 交换字节序以主持字节序
  • VALUE 是一个 char[32]
  • 我刚刚发现Swift:(UInt(data.0) << 6) + (UInt(data.1) >> 2)做同样的事情.可以解释一下吗?
  • 我愿意回来一个Swift Uint(UInt64)

谢谢 !

c pointers endianness swift

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

在C中将整数复制到char缓冲区

  uint32_t after = 0xe1ca95ee;
  char new_buf[4];
  memcpy(new_buf, &after, 4);
  printf("%x\n", *new_buf); // I want to print the content of new_buf
Run Code Online (Sandbox Code Playgroud)

我想要的内容复制afternew_buf.但结果令人困惑.printf给了我ffffffee.它看起来像一个地址.我已经取消引用了new_buf.

根据评论,我不能使用memcpystrncpy执行此任务.但为什么?memcpy并且strncpy只是为了处理char *?但内容after是在记忆中.

PS:我知道我应该使用sprintfsnprintf.如果你能解释为什么memcpystrncpy不适用于这种情况,我很感激.

c

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