- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我一直在读到,在 C 中,使用指针算术通常比数组访问的下标更快。即使使用现代(据称是优化的)编译器也是如此吗?
如果是这样,当我开始从学习 C 转向 Objective-C 和 Cocoa 时,情况是否仍然如此?在 Mac 上?
在 C 和 Objective-C 中,哪种数组访问的首选编码风格是?哪个(由各自语言的专业人士)认为更清晰、更“正确”(因为缺乏更好的术语)?
最佳答案
您需要了解这种说法背后的原因。你有没有问过自己为什么它更快?让我们比较一些代码:
int i;
int a[20];
// Init all values to zero
memset(a, 0, sizeof(a));
for (i = 0; i < 20; i++) {
printf("Value of %d is %d\n", i, a[i]);
}
它们都是零,真是令人惊讶:-P 问题是,
a[i]
意味着什么?实际上是低级机器代码?它的意思是
a
在内存中。i
乘以单个项目的大小 a
到那个地址(int 通常是四个字节)。a
获取一个值时,
a
的基地址与
i
的乘法结果相加由四。如果只是解引用一个指针,则不需要执行步骤1.和2.,只需执行步骤3。
int i;
int a[20];
int * b;
memset(a, 0, sizeof(a));
b = a;
for (i = 0; i < 20; i++) {
printf("Value of %d is %d\n", i, *b);
b++;
}
此代码
可能更快......但即使是这样,差异也很小。为什么会更快? “*b”与上述第 3 步相同。但是,"b++"与步骤 1. 和步骤 2 不同。 "b++"将指针增加 4。
(important for newbies: running
++
on a pointer will not increase thepointer one byte in memory! It willincrease the pointer by as many bytesin memory as the data it points to isin size. It points to anint
and theint
is four bytes on my machine, so b++increases b by four!)
i
快按四并将其添加到指针。在任何一种情况下,您都有一个加法,但在第二个中,您没有乘法(您避免了一次乘法所需的 CPU 时间)。考虑到现代 CPU 的速度,即使阵列是 1 个 mio 元素,我想知道您是否真的可以对差异进行基准测试。
-Os
,这意味着优化代码大小和速度,但不要做会显着增加代码大小的速度优化,不像
-O2
,更不像
-O3
):
_main:
pushl %ebp
movl %esp, %ebp
pushl %edi
pushl %esi
pushl %ebx
subl $108, %esp
call ___i686.get_pc_thunk.bx
"L00000000001$pb":
leal -104(%ebp), %eax
movl $80, 8(%esp)
movl $0, 4(%esp)
movl %eax, (%esp)
call L_memset$stub
xorl %esi, %esi
leal LC0-"L00000000001$pb"(%ebx), %edi
L2:
movl -104(%ebp,%esi,4), %eax
movl %eax, 8(%esp)
movl %esi, 4(%esp)
movl %edi, (%esp)
call L_printf$stub
addl $1, %esi
cmpl $20, %esi
jne L2
addl $108, %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
ret
与第二个代码相同:
_main:
pushl %ebp
movl %esp, %ebp
pushl %edi
pushl %esi
pushl %ebx
subl $124, %esp
call ___i686.get_pc_thunk.bx
"L00000000001$pb":
leal -104(%ebp), %eax
movl %eax, -108(%ebp)
movl $80, 8(%esp)
movl $0, 4(%esp)
movl %eax, (%esp)
call L_memset$stub
xorl %esi, %esi
leal LC0-"L00000000001$pb"(%ebx), %edi
L2:
movl -108(%ebp), %edx
movl (%edx,%esi,4), %eax
movl %eax, 8(%esp)
movl %esi, 4(%esp)
movl %edi, (%esp)
call L_printf$stub
addl $1, %esi
cmpl $20, %esi
jne L2
addl $124, %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
ret
嗯,这是不同的,这是肯定的。 104 和 108 的数字差异来自变量
b
(在第一个代码中,堆栈上少了一个变量,现在我们多了一个,改变了堆栈地址)。
for
中的真实代码差异循环是
movl -104(%ebp,%esi,4), %eax
相比
movl -108(%ebp), %edx
movl (%edx,%esi,4), %eax
实际上在我看来,第一种方法似乎更快(!),因为它发出一个 CPU 机器代码来执行所有工作(CPU 为我们完成所有工作),而不是有两个机器代码。另一方面,下面的两个汇编命令的运行时间可能比上面的要短。
i
乘以 4,然后在获取值之前将两者相加),这些语句曾经是绝对真理古往今来越来越值得怀疑。还有谁知道 CPU 内部是如何工作的?上面我将一个组装指令与另外两个指令进行了比较。
NSArray
或
NSMutableArray
),这是完全不同的野兽。但是,在这种情况下,无论如何您都必须使用方法访问这些数组,没有可供选择的指针/数组访问。
关于objective-c - 通过指针运算与 C 中的下标访问数组值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/233148/
我刚接触 C 语言几周,所以对它还很陌生。 我见过这样的事情 * (variable-name) = -* (variable-name) 在讲义中,但它到底会做什么?它会否定所指向的值吗? 最佳答案
我有一个指向内存地址的void 指针。然后,我做 int 指针 = void 指针 float 指针 = void 指针 然后,取消引用它们以获取值。 { int x = 25; vo
我正在与计算机控制的泵进行一些串行端口通信,我用来通信的 createfile 函数需要将 com 端口名称解析为 wchar_t 指针。 我也在使用 QT 创建一个表单并获取 com 端口名称作为
#include "stdio.h" #include "malloc.h" int main() { char*x=(char*)malloc(1024); *(x+2)=3; --
#include #include main() { int an_int; void *void_pointer = &an_int; double *double_ptr = void
对于每个时间步长,我都有一个二维矩阵 a[ix][iz],ix 从 0 到 nx-1 和 iz 从 0 到 nz-1。 为了组装所有时间步长的矩阵,我定义了一个长度为 nx*nz*nt 的 3D 指针
我有一个函数,它接受一个指向 char ** 的指针并用字符串填充它(我猜是一个字符串数组)。 *list_of_strings* 在函数内部分配内存。 char * *list_of_strings
我试图了解当涉及到字符和字符串时,内存分配是如何工作的。 我知道声明的数组的名称就像指向数组第一个元素的指针,但该数组将驻留在内存的堆栈中。 另一方面,当我们想要使用内存堆时,我们使用 malloc,
我有一个 C 语言的 .DLL 文件。该 DLL 中所有函数所需的主要结构具有以下形式。 typedef struct { char *snsAccessID; char *
指针, C语言的精髓 莫队先咕几天, 容我先讲完树剖 (因为后面树上的东西好多都要用树剖求 LCA). 什么是指针 保存变量地址的变量叫做指针. 这是大概的定义, 但是Defad认为
我得到了以下数组: let arr = [ { children: [ { children: [], current: tru
#include int main(void) { int i; int *ptr = (int *) malloc(5 * sizeof(int)); for (i=0;
我正在编写一个程序,它接受一个三位数整数并将其分成两个整数。 224 将变为 220 和 4。 114 将变为 110 和 4。 基本上,您可以使用模数来完成。我写了我认为应该工作的东西,编译器一直说
好吧,我对 C++ 很陌生,我确定这个问题已经在某个地方得到了回答,而且也很简单,但我似乎找不到答案.... 我有一个自定义数组类,我将其用作练习来尝试了解其工作原理,其定义如下: 标题: class
1) this 指针与其他指针有何不同?据我了解,指针指向堆中的内存。如果有指向它们的指针,这是否意味着对象总是在堆中构造? 2)我们可以在 move 构造函数或 move 赋值中窃取this指针吗?
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: C : pointer to struct in the struct definition 在我的初学者类
我有两个指向指针的结构指针 typedef struct Square { ... ... }Square; Square **s1; //Representing 2D array of say,
变量在内存中是如何定位的?我有这个代码 int w=1; int x=1; int y=1; int z=1; int main(int argc, char** argv) { printf
#include #include main() { char *q[]={"black","white","red"}; printf("%s",*q+3); getch()
我在“C”类中有以下函数 class C { template void Func1(int x); template void Func2(int x); }; template void
我是一名优秀的程序员,十分优秀!