为什么 C 在指针运算期间抽象掉 sizeof?

问题描述

我在 C 中从头开始重新创建一个数组,并实现了诸如追加、插入等常用函数。我得到了大部分方法,但是当我尝试在索引 1 处运行我的“插入”函数时(而不是0),我在访问最后一个元素的“for循环”输出打印期间开始出现段错误。我只使用循环进行打印,否则为了调整大小和移动,我使用了内存管理功能,如 memmove、strdup 和 realloc。我还注意到它覆盖了索引 1,而不是像我在 memmove 中预期的那样滑动数组。

我发现我在做指针运算是错误的,每次都使用 sizeof 运算符,但这让我思考,为什么 C 在 malloc() 之外从我们这里抽象出来?如果我们想以小于一个整体的单位进行算术,我们将如何做到这一点?我们是否会将该值复制到另一个变量并在那里执行,是否会有这样的用例?

有趣的是我已经这样做了几个月没有任何问题,事实上我可以发誓这是必要的一次,但也许我没有直接思考。也许那是 malloc 或 realloc 或其他东西,或者也许我很幸运。

这是我正在谈论的一些代码(运行良好):

void arr_insert(Array *arr,char *element,int index)
{
  // Throw an error if the index is greater than the current count
  if (index > arr->count)
  {
    fprintf(stderr,"Index out of range");
    printf("Index out of range in arr_insert\n");
    return;
  }
  // Resize the array if the number of elements is over capacity
  if (arr->count == arr->capacity) resize_array(arr);
  // Move every element after the insert index to the right one position
  memmove(arr->elements + ((index + 1)),arr->elements + ( index),(arr->count - index) * sizeof(char *));
  // copy the element (hint: use `strdup()`) and add it to the array
  *(arr->elements + (index)) = strdup(element);
  // Increment count by 1
  arr->count++;

这是我之前失败的那条线

 memmove(arr->elements + (sizeof(char *) * (index + 1)),arr->elements + (sizeof(char *) * index),(arr->count - index) * sizeof(char *));

解决方法

  1. 因为它使数组索引起作用(请记住,#import <WebKit/WKWebViewConfiguration.h> WKWebViewConfiguration *theConfiguration = [[WKWebViewConfiguration alloc] init]; self.webView = [[WKWebView alloc] initWithFrame:CGRectMake(self.view.center.x-(320/2),self.view.center.y-(240/2),320,240) configuration:theConfiguration]; NSURL *nsurl=[NSURL URLWithString:@"http://70.176.81.136:81/CFC878/1"]; NSURLRequest *nsrequest=[NSURLRequest requestWithURL:nsurl]; [_webView loadRequest:nsrequest]; [self.view insertSubview:self.webView atIndex:14]; 只是 a[i]。)
  2. 因为它确保指针算术的结果始终是针对该类型正确对齐的指针。
  3. 如果您想直接将其作为一系列字节对其进行操作,您可以将指针投射到 *(a+i)(这就是 void *memcpy 之类的函数的工作方式),并且您可以把它扔回去 (write,malloc)。但是,做类似 realloc(其中 (int *)((void *)x + 1))的事情并不能保证做任何有用的事情,甚至不能保证行为一致。
,

代替这些怪物使用一些临时变量来使代码更具可读性。

字节级别的指针算法:

char *dest = (char *)arr->elements + sizeof(char *) * (index + 1);
char *src =  (char *)arr->elements + sizeof(char *) * index;

memmove(dest,src,(arr->count - index) * sizeof(char *));