- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
有时在C语言中,有必要从部分写入的数组中读取可能写入的项目,例如:
如果已写入该项目,则读取将产生实际上已写入的值,并且
如果尚未写入该项目,则读取会将未指定的位模式转换为适当类型的值,而不会产生副作用。
从头开始找到解决方案的成本很高,但是验证所提出的解决方案的成本却很低。如果一个数组在所有情况下都具有解决方案,而在其他情况下则具有任意位模式,则读取该数组,测试其是否持有有效的解决方案,并仅在数组中的解决方案无效时才慢慢计算该解决方案,可能是有用的优化。
如果可以保证尝试读取类型如uint32_t
的未写数组元素总是产生适当类型的值,那么有效地,这种方法将是简单而直接的。即使该要求仅适用于unsigned char
,它仍然可能可行。不幸的是,编译器有时的行为似乎是读取不确定的值,即使类型为unsigned char
,也可能会产生与该类型的值不一致的行为。此外,“缺陷报告”中的讨论表明,涉及不确定值的运算会产生不确定结果,因此,即使给出unsigned char x, *p=&x; unsigned y=*p & 255; unsigned z=(y < 256);
之类的内容,z
也有可能接收值0
。
据我所知,该函数:
unsigned char solidify(unsigned char *p)
{
unsigned char result = 0;
unsigned char mask = 1;
do
{
if (*p & mask) result |= mask;
mask += (unsigned)mask; // Cast only needed for capricious type ranges
} while(mask);
return result;
}
unsigned char
的值,即使该存储恰好持有不确定值也是如此。但是,鉴于获得所需效果所需的机器代码通常应等效于返回
x
,因此这种方法似乎很慢且笨拙。
unsigned char
范围内的值?
fwrite
可以用于部分扭曲的结构或数组,我都认为可以以这种方式使用的I / O例程(为未设置的部分写入任意值)应为比在这种情况下可能会跳脱的质量更高。
unsigned char solidify_alt(unsigned char *p)
{ return *p; }
unsigned char
的地址优化为例如。一个32位寄存器,上面的函数可能会盲目地返回该寄存器的内容,而不会将其裁剪到0-255的范围内。如果这是唯一的问题,则要求调用者手动裁剪此类函数的结果将很烦人,但可以生存。不幸...
void send_byte(unsigned char *p, unsigned int n)
{
while(n--)
OUTPUT_REG = solidify_alt(*p++) | 0x0200;
}
void send_string4(char *st)
{
unsigned char buff[5]; // Leave space for zero after 4-byte string
strcpy((char*)buff, st);
send_bytes(buff, 4);
}
solidify_alt
而不是
solidify
,因此编译器可以合法地将其转换为:
void send_string4(char *st)
{
unsigned buff0, buff1, buff2, buff3;
buff0 = st[0]; if (!buff0) goto STRING_DONE;
buff1 = st[1]; if (!buff1) goto STRING_DONE;
buff2 = st[2]; if (!buff2) goto STRING_DONE;
buff3 = st[3];
STRING_DONE:
OUTPUT_REG = buff0 | 0x0200;
OUTPUT_REG = buff1 | 0x0200;
OUTPUT_REG = buff2 | 0x0200;
OUTPUT_REG = buff3 | 0x0200;
}
((unsigned char)solidify_alt(*p++) | 0x0200) & 0x02FF)
,编译器仍可以简化该表达式以产生上面给出的代码。
最佳答案
这不是答案,而是扩展的评论。
立即的解决方案是让编译器提供一个内置的(例如assume_initialized(variable [, variable ... ]*)
),该生成器不生成任何机器代码,而只是使编译器将要定义但未知的指定变量(标量或数组)的内容。
例如,使用另一个编译单元中定义的伪函数可以达到类似的效果
void define_memory(void *ptr, size_t bytes)
{
/* Nothing! */
}
define_memory(some_array, sizeof some_array)
),以阻止编译器将数组中的值视为不确定的;之所以可行,是因为在编译时,编译器无法确定是否未指定值,因此必须考虑将其指定为已定义(已定义但未知)。
memrepeat(ptr, first, bytes)
函数:对于
memmove()
,与
memcpy()
相对应的函数将重复
first
到
ptr
到
ptr+first
的字节。像
ptr+bytes-1
一样,它将对数据的存储表示形式起作用,因此,即使
memmove()
到
ptr
包含陷阱表示形式,也不会实际触发陷阱。
double nums[7] = { 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0 };
memrepeat(nums, 2 * sizeof nums[0], sizeof nums);
double nums[7] = { 7.0, 6.0, 7.0, 6.0, 7.0, 6.0, 7.0 };
ptr+first
,其中
memsetall(data, size, count)
是重复存储单元的大小,而
size
存储单元总数(因此< cc>单元实际上是被复制的。)特别是,这使得使用非临时性存储来进行复制的简单实现(从初始存储单元读取);另一方面,
count
只能复制完整存储单元,与
count-1
不同,
memsetall()
将使
memrepeat()
中的第7个元素保持不变-即,在上面的示例中,它的产量为
memsetall(nums, 2 * sizeof nums[0], 3);
。)
nums[]
或
{ 7.0, 6.0, 7.0, 6.0, 7.0, 6.0, 1.0 }
,甚至可以针对特定的体系结构和编译器对其进行优化,但是编写可移植的优化版本却很困难。
memrepeat()
(或
memsetall()
)的基于循环的实现在通过例如GCC,因为编译器无法将函数调用模式合并到单个操作中。
memcpy()
和
memmove()
内联到目标和用例优化的内部版本中,并且对于这样的
memcpy()
和/或
memmove()
函数执行此操作将使其可移植。在x86-64上的Linux中,GCC内联已知大小的调用,但是将函数调用保留在仅在运行时知道大小的地方。
memrepeat()
,
memsetall()
和
getline()
首先加入;它们对我们可以教新的C程序员的代码产生更大的积极影响。)
关于c - 从不确定值到未指定值的有效转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47611338/
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭 6 年前。 Improve t
notificationCenterPublisher = NotificationCenter.default .publisher(for: .NSManagedObjec
我有以下 Rust 代码: #[inline(never)] fn x() -> i32 { 21 } pub fn main() -> i32 { x() } 如果没有优化 (-C
notificationCenterPublisher = NotificationCenter.default .publisher(for: .NSManagedObjec
我有以下 Rust 代码: #[inline(never)] fn x() -> i32 { 21 } pub fn main() -> i32 { x() } 如果没有优化 (-C
假设我的 ASPX 页面没有内联 C# 代码块。 所以,我可以安全地设置 ...在我的 web.config 文件中,不用担心编译错误。 就性能而言,使用以下设置是否会有任何损失? 即“自动”检测
应用程序.js var win1 = Titanium.UI.createWindow({ title:'Tab 1', backgroundColor: 'black', l
基本上,我正在为实现多级优先级队列的 xv6 内核实现一个调度程序。我有一个严重的问题,我不明白,我类(class)的助教不明白,我已经错过了这个项目的最后期限,所以现在帮助我不会给我任何加分 - 但
我想避免 git 自动 merge 我的 composer.json。这样我就可以在 develop 分支中有一个使用 dev-develop 包的 composer.json,而 master 中的
当比较两种不同的算法实现时(因此,不关心它们的绝对性能,而只关心相对性能)我是否最好强制 Java 只运行解释代码? 也就是说,打开 -Xint 标志会更好吗? 最佳答案 我不认为禁用 JIT 会更好
class A{ const size_t number; public: A(size_t number): number(number) {} void f(){
问题 寻找在以下之间切换的方法: 总是 从不 仅在静默模式下 仅当不处于静默模式时 这些选项在手机上的路径---菜单>>设置>>声音>>振动---找到。 通过手机导航很容易更改(顺便说一句,我的手机是
如何设置电源设置关闭:从不(关闭显示器=从不,让计算机进入休眠状态=从不),通过c#代码 最佳答案 这个问题中给出的链接可以告诉你一个方法。 Programmatically change Windo
我是一名优秀的程序员,十分优秀!