C 指针算法

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

有人有关于指针运算的好文章或解释(博客、例子)吗?图中的观众是一群学习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
print_out(pb); // possibly outputs 0x0 (if NULL is actually bit-wise 0x0)
(请注意,对包含空指针值的指针严格递增是未定义的行为。我们使用null是因为我们只对指针的值感兴趣。通常,在指向数组元素时仅使用递增/递减)

下面展示了两个重要的概念

  • 将整数与指针相加/相减意味着将指针向前/向后移动N个元素。所以,如果一个int是4字节大,那么在我们的平台上,pa可以在递增1后包含0x4
  • 用另一个指针减去一个指针意味着得到它们的距离,用元素来度量。所以从pa中减去pb将得到1,因为它们有一个元素距离
在一个实际例子上。假设您编写了一个函数,人们为您提供了一个开始和结束指针(在C++中非常常见):


ptrdiff\u t
是什么类型的(结束-开始)。对于某些编译器,它可能是“int”的同义词,但对于另一个编译器,它可能是另一种类型。我们无法知道,因此我们选择通用类型def
ptrdiff\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 ]