C 指针算法
有人有关于指针运算的好文章或解释(博客、例子)吗?图中的观众是一群学习C和C++的java程序员。C 指针算法,c,pointers,pointer-arithmetic,C,Pointers,Pointer Arithmetic,有人有关于指针运算的好文章或解释(博客、例子)吗?图中的观众是一群学习C和C++的java程序员。 首先,视频可能会有所帮助。这是一段关于指针的精彩视频。对于算术,以下是一个示例: int * pa = NULL; int * pb = NULL; pa += 1; // pa++. behind the scenes, add sizeof(int) bytes assert((pa - pb) == 1); print_out(pa); // possibly outputs 0x4 pr
首先,视频可能会有所帮助。这是一段关于指针的精彩视频。对于算术,以下是一个示例:
int * pa = NULL;
int * pb = NULL;
pa += 1; // pa++. behind the scenes, add sizeof(int) bytes
assert((pa - pb) == 1);
print_out(pa); // possibly outputs 0x4
print_out(pb); // possibly outputs 0x0 (if NULL is actually bit-wise 0x0)
(请注意,对包含空指针值的指针严格递增是未定义的行为。我们使用null是因为我们只对指针的值感兴趣。通常,在指向数组元素时仅使用递增/递减)
下面展示了两个重要的概念
- 将整数与指针相加/相减意味着将指针向前/向后移动N个元素。所以,如果一个int是4字节大,那么在我们的平台上,pa可以在递增1后包含0x4
- 用另一个指针减去一个指针意味着得到它们的距离,用元素来度量。所以从pa中减去pb将得到1,因为它们有一个元素距离李>
ptrdiff\u t
是什么类型的(结束-开始)。对于某些编译器,它可能是“int”的同义词,但对于另一个编译器,它可能是另一种类型。我们无法知道,因此我们选择通用类型defptrdiff\u t
这里是我学习指针的地方:
一旦理解了指针,指针算法就很容易了。它与常规算术的唯一区别在于,要添加到指针的数字将乘以指针所指向类型的大小。例如,如果您有一个指向int
的指针,并且int
的大小为4个字节,(指针指向int+4)
将计算为前面16个字节(4个int)的内存地址
所以当你写作的时候
(a_pointer + a_number)
在指针运算中,真正发生的是
(a_pointer + (a_number * sizeof(*a_pointer)))
在正则算术中,
我考虑了指针算术的一个很好的例子:下面的字符串长度函数:int length(char *s)
{
char *str = s;
while(*str++);
return str - s;
}
应用NLP,称之为地址算法。”指针的恐惧和误解主要是因为它们是由错误的人和/或在错误的阶段以错误的方式用错误的例子教授的。难怪没有人“得到”它 当教授指针时,教员们会说“p是指向a的指针,p的值是a的地址”等等。它就是不起作用。这是你用来建造的原材料。用它练习,你的学生就会得到它 “int a”,a是一个整数,它存储整数类型的值。 'int*p',p是一个'int-star',它存储'int-star'类型的值 “a”是获取存储在a中的“what”整数的方式(尽量不要使用“a的值”) “&a”是获取存储a本身的“位置”的方式(尝试说“地址”) “b=a”若要使其工作,两侧必须为同一类型。如果A是int,则B必须能够存储int(因此,α-yxb),空白填充“int”)。 “p=&a”若要使其工作,两侧必须为同一类型。如果a是整数,&a是地址,那么p必须能够存储整数的地址。(因此,α-yxp p,空白填充“int *”) 现在以不同的方式写入int*p以显示类型信息: int*| p 什么是“p”?回答:是int*。所以“p”是一个整数的地址 int |*p 什么是“*p”?答:它是一个“int”。所以“*p”是一个整数 现在进入地址算法: INTA; a=1; a=a+1 我们在“a=a+1”中做什么?把它想象成“下一个”。因为a是一个数字,这就像说“下一个数字”。因为a表示1,所以说“下一步”将表示为2 //错误的例子。你已经被警告了!!! int*p INTA; p=&a; p=p+1 在‘p=p+1’中我们在做什么?它仍然在说“下一步”。这一次,p不是一个数字,而是一个地址。所以我们说的是“下一个地址”。下一个地址取决于数据类型,更具体地说取决于数据类型的大小 printf(“%d%d%d”、sizeof(char)、sizeof(int)、sizeof(float)) 因此,地址的“下一步”将向前移动sizeof(数据类型)
这对我和我曾经教过的所有人都很有用。所以,要记住的关键是指针只是一个字大小的变量,它是为解引用而键入的。这意味着无论它是void*、int*、long-long**,它仍然只是一个单词大小的变量。这些类型之间的区别在于编译器认为被解除引用的类型是什么。只是澄清一下,单词大小意味着虚拟地址的宽度。如果您不知道这意味着什么,请记住在64位机器上,指针是8字节,而在32位机器上,指针是4字节。地址的概念在理解指针时非常重要。地址是能够唯一标识内存中某个位置的数字。内存中的所有内容都有一个地址。出于我们的目的,我们可以说每个变量都有一个地址。这并不一定总是正确的,但编译器允许我们假设这一点。地址本身是字节粒度的,这意味着0x0000000指定内存的开头,0x00000001是内存中的一个字节。这意味着通过向指针添加一个字节,我们将一个字节向前移动到内存中。现在,让我们看看数组。如果创建一个quux类型的数组,其大小为32个元素,那么它将从分配的开始到分配的开始再加上32*sizeof(quux),因为数组的每个单元格都是sizeof(quux)大的。所以,当我们用数组[n]指定一个数组的元素时,这只是*(数组+sizeof(qux)*n)的语法糖(简写)。指针算法实际上只是改变你所指的地址,这就是为什么我们可以用
while(*n++ != '\0'){
len++;
}
因为我们只是一个字节一个字节地扫描,直到找到一个零。希望有帮助 有几种方法可以解决这个问题 直观的方法,这是大多数C/C++程序员
while(*n++ != '\0'){
len++;
}
p1 = arr + 3 ; // p1 == & arr[ 3 ]
p2 = p1 - 2 ; // p1 == & arr[ 1 ]