0

我像这样初始化了数组

CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, bounds);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
unsigned char *rawData = malloc(height * width * 4);
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

但是,当我尝试通过 NSLog 检查计数时,我总是得到 4(特别是 4/1)。

int count = sizeof(rawData)/sizeof(rawData[0]);
NSLog(@"%d", count);

然而,当我 NSLog 单个元素的值时,它返回非零值。

前任。
CGFloat f1 = rawData[15];

CGFloat f2 = rawData[n], 在n哪里image width*height*4;

//我没想到这会起作用,因为最后一个元素应该是 n-1

最后,我尝试了

int n = lipBorder.size.width *lipBorder.size.height*4*2; //lipBorder holds the image's dimensions, I tried multiplying by 2 because there are 2 pixels for every CGPoint in retina
CGFloat f = rawData[n];

这将每次为同一图像返回不同的值(例如 0.000、115.000、38.000)。

如何确定计数/值如何存储到数组中?

4

2 回答 2

1

rawData是指向 unsigned char 的指针,因此它的大小为 32 位(4 字节)[1]rawData[0]是一个无符号字符,因此它的大小是 8 位(1 个字节)。因此,4/1

您之前可能已经看到过使用数组完成此操作,它确实可以按您的预期工作:

unsigned char temp[10] = {0};
NSLog(@"%d", sizeof(temp)/sizeof(temp[0])); // Prints 10

但是请注意,您正在处理指向unsigned char 的指针,而不是 unsigned char 的数组- 语义不同,因此为什么这在您的情况下不起作用。

如果您想要缓冲区的大小,那么简单地使用会更好height * width * 4,因为这就是您传递给的内容malloc。如果你真的必须,你可以将它除以sizeof(char)sizeof(rawData[0])得到元素的数量,但由于它们是字符,你无论如何都会得到相同的数字。

现在,rawData只是某处的一块内存。在它之前和之后还有其他的记忆。因此,如果您尝试执行类似 的操作rawData[height * width * 4],您实际上是在尝试访问分配给 的块之后rawData的下一个内存字节。这是未定义的行为,可能导致返回随机垃圾值[2](如您所见),返回一些“未分配的内存”标记值,或发生分段错误。


[1]:iOS 是一个 32 位平台
[2]:可能是上次合法使用该内存位置时放入的任何值。

于 2013-08-18T21:07:46.417 回答
0

malloc 返回的指针是一个 void* 指针,这意味着它返回一个指向内存地址的指针。返回的宽度和高度似乎为 0。这可以解释为什么只为数组分配 4 个字节。

你也说你试过

int n = lipBorder.size.width *lipBorder.size.height*4*2; //lipBorder holds the image's dimensions, I tried multiplying by 2 because there are 2 pixels for every CGPoint in retina
    CGFloat f = rawData[n];    

并且每次都收到不同的值。考虑到您的数组只有 4 个字节长,并且您正在访问一个在内存中更靠前的内存区域,这种行为是可以预料的。值发生变化的原因是您正在访问不在数组中的内存,而是在一个 lipBorder.size.width *lipBorder.size.height*4*2 - 4字节通过数组末尾的内存位置。C 绝不会阻止您访问程序中的任何内存。如果您访问的内存超出了程序的限制,您将收到分段错误。

因此,您可以访问n + 1n + 2n + whatever元素。这仅意味着您正在访问通过数组末尾传递的内存。

递增指针 rawdata 会将内存地址移动一个字节。递增和 int 指针会将内存地址递增 4 个字节(sizeof(int))。

于 2013-08-18T22:05:40.773 回答