开发者

Why does CRC return different value when inside Objective-C method instead of static inline function?

开发者 https://www.devze.com 2023-03-26 18:05 出处:网络
I need to add CRC calculation to my app and found Apple\'s sample ZipBrowser project. This project uses the CRC function inside zlib.h:

I need to add CRC calculation to my app and found Apple's sample ZipBrowser project. This project uses the CRC function inside zlib.h:

#import <zlib.h>

static inline uint32_t _crcFromData(NSData *data) {
    uint32_t crc = crc32(0, NULL, 0);
    return crc32(crc, [data bytes], [data length]);
}

(Because I don't really understand the significance of static inline) I thought I'd make the function look like a typical Objective-C method:

- (uint32_t)_crcFromData:(NSData *)data
{
    uint32_t crc = crc32(0, NULL, 0);
    return crc32(crc, [data bytes], [data length]);
}

This produces different answers from static inline! Why is that?

In addition, both give me "Implicit conversion loses integer precision" compiler warnings.

Next, I cast crc32 and [data length] (e.g. return (uint32_t)crc32...). The compiler warnings went away of course but the return values are still different from static inline.

I removed the casts again because I'm not sure if the CRC will be sensitive to changes in width of the variables I'm using (so it now looks exactly like the code pasted above).

(Using NSLog, it seems that the difference occurs when I call crc32(crc, [data bytes], [data length]); not when I return the value from static inline function or Obj-C method. In other words, it seems to make a difference where you call the zlib function from.)

Next, I found sample code for adding a CRC algorithm as an NSData category and I used this code to compare answers against my zlib calls. Comparing 3 approaches, I get different results depending on what data I pass in (sometimes 2 will match but not always the same 2)!

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    NSFileHandle *fileHandle = [NSFileHandle
                                fileHandleForReadingAtPath:@"/Users/steve/Music/iTunes/iTunes Music/pops1/001.mp3"];

    NSLog(@"Cocoa style declaration: %u", [self _crcFromData:[fileHandle readDataOfLength:1024]]); //returns: 3157848792
    NSLog(@"Static inline declaration: %u", _crcFromData([fileHandle readDataOfLength:1024])); //returns: 4021661486
    NSLog(@"Self-coded CRC: %u", [[fileHandle readDataOfLength:1024] crc32]); //returns: 4021661486

    NSLog(@"Cocoa style declaration: %u", [self _crcFromData:[fileHandle readDataOfLength:500]]); //returns: 42187130
    NSLog(@"Static inline declaration: %u", _crcFromData([fileHandle readDataOfLength:500])); //retu开发者_如何学Gorns: 42187130
    NSLog(@"Self-coded CRC: %u", [[fileHandle readDataOfLength:500] crc32]); //returns: 4168292535

    NSLog(@"Cocoa style declaration: %u", [self _crcFromData:[fileHandle readDataOfLength:5000]]); //returns: 2401083626
    NSLog(@"Static inline declaration: %u", _crcFromData([fileHandle readDataOfLength:5000])); //returns: 3786034839
    NSLog(@"Self-coded CRC: %u", [[fileHandle readDataOfLength:5000] crc32]); //returns: 2526276347

}

Given the different answers, I assume that the safest approach is the static inline approach used in the Apple sample project.

Wrapping this into more specific questions:

  • What are the static inline and the Objective-C versions doing differently that causes them to receive different values from CRC32?
  • What is the best way to avoid the compiler errors? Use different data types (that don't affect the result of the CRC calculation)? Or suppress compiler warnings?
  • If I should just suppress compiler warnings, I would want to do it on just the file. I've found articles (e.g. http://joshua.nozzi.name/2011/03/per-file-compiler-flags-in-xcode-4/) on where to make the setting but no article on how to make the setting. I've seen long lists of flags such as Wpadded, Wlong-long, Werror, etc but nothing that tells me which is the one I need, and how to actually set it as plain text inside the per-file setting in Xcode 4 (e.g. Wconversion=something?).
  • Finally, and more to the point, which is the correct approach? It shouldn't be possible to have different CRC values otherwise this defeats the whole purpose of CRC!

Sorry about the roundabout way I've asked this question but I'm trying to give a bigger picture of my problem in case I've made some basic wrong assumption along the way resulting in me asking the wrong questions. Thank you.

UPDATE

The sample project compiles perfectly but when I paste this code into my own project I get the compiler warnings. It seems that this is because that project has "Implicit conversion to 32 Bit Type" in Build Settings set to "Yes". As this is project-wide, I think it would be better not to use this in my own app if I can do it per-file.

0

精彩评论

暂无评论...
验证码 换一张
取 消