我从C++ faq中读到“应该在首次使用附近声明本地人”。此外,出于性能原因,Scott Meyer 的 Effective C++ Item 26 也建议这样做。但我最近碰巧听到有人说,编译器足够聪明,可以在定义变量的地方优化变量,而不管它们在函数中实际使用的范围如何。他建议在函数顶部声明变量以方便理解(虽然我不买这个原因)。他关于编译器优化是否正确?
(问题是关于性能和编译器优化。不是代码可读性)。
因此,根据此处的C编译器标准:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf
我们发现无法精确确定在C编译器中如何实现位字段的要求。显然,只要位域的行为与任何其他标量域一样,任何事情都会发生。文档部分6.7.2.1-10说:
“一个实现可以分配任何足够大的可寻址存储单元来容纳一个位域。如果有足够的空间,则紧跟在结构中另一个位域之后的位域应打包到同一单元的相邻位中。如果不足,保留空间,是否将不合适的位字段放入下一个单元或与相邻单元重叠是由实现定义的。一个单元内位字段的分配顺序(高位到低位或低位)到高级)是由实现定义的。可寻址存储单元的对齐方式未指定。”
对于许多声称“您不能信任位域”或“位域不可移植”的人来说,对编译器的迫在眉睫的自由似乎是一站式服务。该警报表明,整个编译器编写者和CPU制造商在星空中密谋,只是因为标准允许而笑着急于做一些奇特的位域调整和对齐。
这些疯狂的波西米亚风格的编译器/ CPU设计人员在哪里致力于保证位域永远不依赖和不便携,这些证据在哪里?我想看看火星上绿人的确凿证据。
我已经附上了简单易懂的C ++源代码,以告诉有关使用C ++编译器的任何系统的位域真相。我要问社区,不是征求意见,而是要向您的系统和编译器提供确切的输出证据,如果它们与发布的结果有所出入。如果与发布的结果相比,我有能力对整个C / C ++社区进行相同/不相同的投票,我想知道百分比是多少?
#include <stdio.h>
/*
A simple program to illustrate the bitfields actual internal compiled layout.
Results depend on machine architecture and compiler implementation and flags.
*/
typedef unsigned long long int ulli;
struct bitf
{
// field bits offset
ulli f0 : 1; // 0
ulli f1 : 2; // 1
ulli f3 : 3; // 3
ulli f7 : 4; // 6
ulli f15 : 5; // …Run Code Online (Sandbox Code Playgroud) 我编写了一个简单的代码来比较对两个数组(两个大小相同)的元素进行操作所花费的时间,一个由 C++ 数组类定义,另一个由普通的 C 样式数组定义。我使用的代码是
#include <iostream>
#include <array>
#include <chrono>
using namespace std;
const int size = 1E8;
const int limit = 1E2;
array<float, size> A;
float B[size];
int main () {
using namespace std::chrono;
//-------------------------------------------------------------------------------//
auto start = steady_clock::now();
for (int i = 0; i < limit; i++)
for (int j = 0; j < size; j++)
A.at(j) *= 1.;
auto end = steady_clock::now();
auto span = duration_cast<seconds> (end - start).count();
cout << "Time taken for array A …Run Code Online (Sandbox Code Playgroud) 我想知道用C语言计算什么更好:
if (x==0)
{
// Some code ...
}
Run Code Online (Sandbox Code Playgroud)
的
if (0==x)
{
// Some code ...
}
Run Code Online (Sandbox Code Playgroud)
我知道最后一个更好,以防程序员忘记第二个“=”并写“0 = x”而不是“0 == x”,因为编译器会抛出错误。
但我的问题是:
我认为这与“左值”和“右值”有关,并且我尝试在我的电脑中进行模拟,但没有任何重要的见解。
我写了一个C程序如下:
void foo(int *a) {
if (a[1000] == a[1000]) {
printf("Hello");
}
}
int main() {
int *a;
foo(a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我期待这个程序崩溃,因为我没有在&a [1000]分配内存,但程序实际上没有崩溃并打印"Hello".我用命令编译了程序
gcc -O0 foo.c
Run Code Online (Sandbox Code Playgroud)
可能是什么原因?
c memory-management compiler-optimization undefined-behavior
请看下面的代码
#include<stdio.h>
int main(void){
int *ptr,a,b;
a = ptr;
b = ptr + 1;
printf("the value of a,b is %d and %d respectively\n",a,b);
printf("the value of a is %d \n",(ptr));
printf("the value of b is %d \n",(ptr+1));
printf("the value of (ptr+1)-ptr is %d \n",(ptr+1)-ptr);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
the value of a,b is 0 and 4 respectively
the value of a is 0
the value of b is 4
the value of (ptr+1)-ptr is 1
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么(ptr + 1)-ptr的值为1而不是4为4-0?是否是由于计算优化?
我一直认为num * 0.5f和num / 2.0f是等价的,因为我认为编译器足够聪明,可以优化除法。所以今天我决定测试一下这个理论,但我发现的结果却难住了我。
给出以下示例代码:
float mul(float num) {
return num * 0.5f;
}
float div(float num) {
return num / 2.0f;
}
Run Code Online (Sandbox Code Playgroud)
x86-64 clang 和 gcc 都会生成以下汇编输出:
mul(float):
push rbp
mov rbp, rsp
movss DWORD PTR [rbp-4], xmm0
movss xmm1, DWORD PTR [rbp-4]
movss xmm0, DWORD PTR .LC0[rip]
mulss xmm0, xmm1
pop rbp
ret
div(float):
push rbp
mov rbp, rsp
movss DWORD PTR [rbp-4], xmm0
movss xmm0, DWORD PTR [rbp-4]
movss xmm1, DWORD PTR …Run Code Online (Sandbox Code Playgroud) c ×5
c++ ×4
arrays ×1
bit-fields ×1
embedded ×1
endianness ×1
intrinsics ×1
lvalue ×1
rvalue ×1
time ×1