当询问C中常见的未定义行为时,灵魂比我提到的严格别名规则更加开明.
他们在说什么?
我在这里浏览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链接后面页面上的代码如下所示:
Run Code Online (Sandbox Code Playgroud)/* 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 …
我的印象是访问union除最后一个成员之外的成员是UB,但我似乎无法找到一个可靠的参考(除了声称它是UB但没有标准支持的答案).
那么,这是不确定的行为?
我正在设计一个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)
或者是其他东西 ?
通常做什么,为什么?
我读的越多,我就越困惑.
相关问题的最后一个问题与我的问题最接近,但是我对所有关于对象生命周期的问题感到困惑,尤其是 - 只读或不读.
直截了当.如我错了请纠正我.
这很好,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 …
在询问"如何实现符合严格别名规则的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,还涉及任何反序列化/解码功能.
我已经阅读了一段时间的严格别名规则,我开始变得非常困惑.首先,我已经阅读了这些问题和一些答案:
根据它们(据我所知),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) 我的公司使用消息服务器将消息const char*收集到a中,然后将其转换为消息类型.
在提出这个问题之后,我对此感到担忧.我不知道消息服务器中有任何不良行为.const变量是否可能不会出现锯齿问题?
例如,假设foo是以下列MessageServer方式之一定义的:
void MessageServer(const char* foo)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) 另一个问题的答案:严格的别名规则和'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 ×6
c++ ×5
glibc ×2
alias ×1
arrays ×1
buffer ×1
const ×1
memcpy ×1
optimization ×1
portability ×1
strlen ×1
type-punning ×1
unions ×1