相关疑难解决方法(0)

什么是严格别名规则?

当询问C中常见的未定义行为时,灵魂比我提到的严格别名规则更加开明.
他们在说什么?

c strict-aliasing undefined-behavior type-punning

778
推荐指数
10
解决办法
19万
查看次数

为什么要快速运行glibc的问题太复杂了?

我在这里浏览strlen代码,想知道是否真的需要代码中使用的优化?例如,为什么下面这样的东西不能同样好或更好?

unsigned long strlen(char s[]) {
    unsigned long i;
    for (i = 0; s[i] != '\0'; i++)
        continue;
    return i;
}
Run Code Online (Sandbox Code Playgroud)

较简单的代码对编译器进行优化是否更好或更容易?

strlen链接后面页面上的代码如下所示:

/* Copyright (C) 1991, 1993, 1997, 2000, 2003 Free Software Foundation, Inc.
   This file is part of the GNU C Library.
   Written by Torbjorn Granlund (tege@sics.se),
   with help from Dan Sahlin (dan@sics.se);
   commentary by Jim Blandy (jimb@ai.mit.edu).

   The GNU C Library is free software; you can redistribute it and/or
   modify it under …
Run Code Online (Sandbox Code Playgroud)

c optimization portability glibc strlen

283
推荐指数
7
解决办法
5万
查看次数

访问非活动的union成员和未定义的行为?

我的印象是访问union除最后一个成员之外的成员是UB,但我似乎无法找到一个可靠的参考(除了声称它是UB但没有标准支持的答案).

那么,这是不确定的行为?

c++ undefined-behavior unions language-lawyer

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

void*或char*用于通用缓冲区表示?

我正在设计一个Buffer类,其目的是代表一块内存.

我的底层缓冲区是一个char*(好吧,boost::shared_array<char>实际上,但它并不重要).

我一直在决定为我的构造函数选择什么样的原型:

我应该去:

Buffer(const void* buf, size_t buflen);
Run Code Online (Sandbox Code Playgroud)

或者:

Buffer(const char* buf, size_t buflen);
Run Code Online (Sandbox Code Playgroud)

或者是其他东西 ?

通常做什么,为什么?

c++ arrays buffer

17
推荐指数
5
解决办法
5724
查看次数

再一次:严格的别名规则和char*

我读的越多,我就越困惑.

相关问题的最后一个问题与我的问题最接近,但是我对所有关于对象生命周期的问题感到困惑,尤其是 - 只读或不读.


直截了当.如我错了请纠正我.

这很好,gcc没有发出警告,我正试图" 通过" 读取类型T(uint32_t)char*:

uint32_t num = 0x01020304;
char* buff = reinterpret_cast< char* >( &num );
Run Code Online (Sandbox Code Playgroud)

但这是"坏"(也是一个警告),我正在尝试"反过来":

char buff[ 4 ] = { 0x1, 0x2, 0x3, 0x4 };
uint32_t num = *reinterpret_cast< uint32_t* >( buff );
Run Code Online (Sandbox Code Playgroud)

第二个如何与第一个不同,特别是当我们谈论重新排序指令(用于优化)时?另外,添加const不会以任何方式改变这种情况.

或者这只是一条直接规则,它明确指出:"这可以在一个方向完成,但在另一个方向不能完成"?我在标准中找不到任何相关内容(特别是在C++ 11标准中搜索过).

C和C++是否相同(因为我读了一条评论,暗示它与2种语言不同)?


我曾经union"解决"这个问题,但仍然看起来并非 100%正常,因为标准无法保证(这表明我只能依赖于最后一次修改的值union).

所以,经过大量阅读,我现在更加困惑.我想只是memcpy"好"的解决方案?


相关问题:


编辑
现实世界的情况:我有一个第三方库(http://www.fastcrypto.org/),它计算UMAC并返回值char[ 4 ].然后我需要将其转换为uint32_t.而且,顺便说一句,lib使用的东西((UINT32 …

c c++ strict-aliasing reinterpret-cast

13
推荐指数
1
解决办法
812
查看次数

编写符合严格别名的memcpy符合条件

在询问"如何实现符合严格别名规则的memcpy函数"时,一般的答案就是这样的

void *memcpy(void *dest, const void *src, size_t n)
{
    for (size_t i = 0; i < n; i++)
        ((char*)dest)[i] = ((const char*)src)[i];
    return dest;
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我理解正确的话,编译器可以自由地重新排序对memcpy的调用并访问dest,因为它可以使用任何其他指针类型的读取重新排序写入char*(严格的别名规则阻止仅对char*的读取进行重新排序)到任何其他指针类型).

这是正确的,如果是的话,有没有办法正确实现memcpy,还是我们应该依赖内置的memcpy?

请注意,这个问题不仅涉及memcpy,还涉及任何反序列化/解码功能.

c c++ strict-aliasing memcpy

8
推荐指数
2
解决办法
1387
查看次数

严格别名规则和glibc的strlen实现

我已经阅读了一段时间的严格别名规则,我开始变得非常困惑.首先,我已经阅读了这些问题和一些答案:

根据它们(据我所知),char使用指向另一种类型的指针访问缓冲区违反了严格的别名规则.但是,glibc实现strlen()有这样的代码(删除了注释和64位实现):

size_t strlen(const char *str)
{
    const char *char_ptr;
    const unsigned long int *longword_ptr;
    unsigned long int longword, magic_bits, himagic, lomagic;

    for (char_ptr = str; ((unsigned long int) char_ptr 
             & (sizeof (longword) - 1)) != 0; ++char_ptr)
       if (*char_ptr == '\0')
           return char_ptr - str;

    longword_ptr = (unsigned long int *) char_ptr;

    himagic = 0x80808080L;
    lomagic = 0x01010101L;

    for (;;)
    { 
        longword = *longword_ptr++;

        if (((longword - lomagic) & himagic) …
Run Code Online (Sandbox Code Playgroud)

c glibc strict-aliasing

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

可以使用const变量避免混淆问题

我的公司使用消息服务器将消息const char*收集到a中,然后将其转换为消息类型.

在提出这个问题之后,我对此感到担忧.我不知道消息服务器中有任何不良行为.const变量是否可能不会出现锯齿问题?

例如,假设foo是以下列MessageServer方式之一定义的:

  1. 作为参数: void MessageServer(const char* foo)
  2. 或者作为顶部的const变量MessageServer:const char* foo = PopMessage();

现在MessageServer是一个巨大的功能,但它从来没有指派任何事情foo在1点但是,MessageServer的逻辑foo 被转换为所选择的消息类型.

auto bar = reinterpret_cast<const MessageJ*>(foo);
Run Code Online (Sandbox Code Playgroud)

bar 将仅从随后读取,但将广泛用于对象设置.

这里是否存在别名问题,或者foo只是初始化并且从未修改过的事实会保存我吗?

编辑:

Jarod42的回答中找到与从铸造没有问题const char*MessageJ*,但我不知道这是有道理的.

我们知道这是非法的:

MessageX* foo = new MessageX;
const auto bar = reinterpret_cast<MessageJ*>(foo);
Run Code Online (Sandbox Code Playgroud)

我们是否以某种方式说这是合法的?

MessageX* foo = new MessageX;
const auto temp = reinterpret_cast<char*>(foo);
auto bar = reinterpret_cast<const MessageJ*>(temp); …
Run Code Online (Sandbox Code Playgroud)

c++ alias const strict-aliasing reinterpret-cast

6
推荐指数
1
解决办法
903
查看次数

如何在不违反严格别名规则的情况下有效地从字符缓冲区复制小数据?

另一个问题的答案:严格的别名规则和'char *'指针表示使用 achar*检查对象的二进制内容T是可以的。但是使用 aT*覆盖 char 缓冲区是不行的。

现在我有一个函数,它采用带有二进制数据的字符缓冲区。在阅读时会做这样的事情:

// unsigned char *pData used to walk through the buffer.
uint32_t value = *(unit32_t*)pData;
pData += 4;
Run Code Online (Sandbox Code Playgroud)

如果我通过这样做打破了严格的别名,还有哪些其他更有效的方法可用?当使用少量字节调用 memcpy 时,编译器会优化它们吗?

c strict-aliasing

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