How to declare packed struct (without padding) for LLVM? - objective-c

It's possible to tell GCC it should not use padding for the struct. This is done using __attribute__((packed)).
typedef struct {
uint8_t startSymbol;
uint8_t packetType;
uint32_t deviceId;
uint16_t packetCRC;
} PacketData __attribute__((packed));
However, newest Xcode uses LLVM and does not recognize the attribute. How to define packed struct for LLVM?
The full description of the problem might be found here
UPDATE I'm using Xcode 4.5.1 for iOS which uses Apple LLVM 4.1 compiler. I'm getting "'packed' attribute ignored" warning in Xcode in the code example above.

Did you actually try it? I just tested it on my machine, and __attribute__((packed)) compiled fine using clang.
Edit: I got the same warning ("Warning: packed attribute unused") for
typedef struct {
int a;
char c;
} mystruct __attribute__((packed));
and in this case sizeof(mystruct) was 8.
However,
typedef struct __attribute__((packed)) {
int a;
char c;
} mystruct;
worked just fine, and sizeof(mystruct) was 5.
Conclusion: it seems that the attribute needs to preceed the struct label in order to get this working.

You can use preprocessor directive to specify byte alignment for the struct so no padding will be done by the compiler:
#pragma pack(1)
typedef struct {
char t1;
long long t2;
char t3;
} struct_size_test;
#pragma options align=reset
See the answer to this question on stackoverflow.

clang 3.5 on Linux -
typedef struct __attribute__((packed)) thing1 { int blah; } THING_ONE;
worked.

Related

Code in Objective C 2008 Does not compile

I'm learning the basics of objective-C by Reading 'Objective C For Dummies'.
I'm using XCode 4.4, and I'm trying to get some simple code to work. This question has been posed online before. However - the code doesn't seem to compile with the new version of XCode.
At issue seems to be the line NSLog (#"Here is some amazing text! %i",c); This throws an 'Expected Expression' Error. Per the previous form posting, I have disabled automatic reference checking in preferences and this still fails.
#include <stdio.h>
int main(int argc, const char * argv[])
{
//declare variables
int a;
int b;
int c;
//set the variables
a = 2;
b = 3;
//Perform the computations
c = a % b;
//Output the results
NSLog (#"Here is some amazing text! %c",c);
return 0;
}
Add #import <Foundation/Foundation.h> at the top, and change the NSLog to this:
NSLog (#"Here is some amazing text! %d",c);
Because %c doesn't mean "a variable called c", but rather a char. %d means an int, which is what c is.
You forgot to include the Foundation header:
#import <Foundation/Foundation.h>
Sidenote: The format specifier should be %d.

How to check if a variable is an object?

Is there any way to do the following at compile-time?
int anInteger = 0;
__if_object(anInteger) {
// send object some messages
}
__if_primitive(anInteger) {
// do something else
}
An dummy situation where this could be used is to define the __add_macro below.
#define __add_macro(var, val) __something_goes_here__
int i = 1;
MyInteger* num = [[MyNumber alloc] initWithValue:1]
__add_macro(i, 4);
__add_macro(num, 4);
// both should now hold 5
Clarification/Simplification
I guess there is no way to do this with one macro. But I still need it to warn if the macro is being used on the wrong datatype. Those two types are: object and non-object).
To check if it is an object, this works:
#define __warn_if_not_object(var) if(0){[(var) class];}
What I need:
#define _warn_if_object(var) if(0){__something_here__}
Again, I need this to happen at compile-time. And it can either throw an error or warning.
Thanks
When you declare an int variable you can really only put an int value in it.
While this is Objective-C, and hence C, so you can bypass just about every type protection mechanism that exists, this is not to be advised. Indeed there is no guarantee whatsoever that a, say, NSNumber reference will even fit into an int variable - and more than enough chance that if you try, and bypass any warnings, some bits will just get tossed making the reference invalid.
So, no, while you can tell what class an object reference refers to, you cannot in general tell whether a variable has an integer value or an object reference in it - you shouldn't even try to put these two very different things into the same variable.
Answer 2
Patrick, your comments and clarification seem to suggest you are not trying to do what the question starts out by asking (how do you determine if the value in an int is an object - answered above, you don't), but something rather different...
I think what you're after is function overloading, and as you seem to be trying to use macros, maybe inline functions as well. Clang supports function overloading, here is program fragment which may show you how to solve your problem:
// Clang likes prototypes so let's give it some
// The following declares two overloaded inline functions:
NS_INLINE void __attribute__((overloadable)) byType(int x);
NS_INLINE void __attribute__((overloadable)) byType(NSNumber *x);
// now some simple definitions:
NS_INLINE void __attribute__((overloadable)) byType(int x)
{
NSLog(#"int version called: %d", x);
}
NS_INLINE void __attribute__((overloadable)) byType(NSNumber *x)
{
NSLog(#"NSNumber version called: %#", x);
}
// now call them, automatically selecting the right function
// based on the argument type
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
int x = 5;
NSNumber *y = [NSNumber numberWithInt:42];
byType(x);
byType(y);
}
The above code when run outputs:
int version called: 5
NSNumber version called: 42
Clang 3 compiles the above code inlining the two calls, so you get the same code as using macros.
please don't mix between scalar values and pointers to objects... it will not end well.
if you insist you can do something with Objective-C++
something like
int sum(int,int);
NSNumber * sum(NSNumber *, NSNumber *);

using sizeof equivalent in objective C

How to find the size of a structure.The use of sizeof() doesnt work in objective C.
sizeof does work for struct in Objective-C. For example:
size_t pointsize = sizeof(NSPoint);
On the other hand, if you are interested in the size of Objective-C instances, use class_getInstanceSize(). For example:
#include <objc/runtime.h>
size_t objsize = class_getInstanceSize([NSObject class]);

declaring integer array in objective c without NSArray.n

(Question updated after first comment)
int max_size = 20;
int h[max_size];
Debugging gives a value of [-1] for h when using max_size to initialize;
If instead I initialize using an integer. So the code is:int h[20] , it works fine.
This was with GCC 4.2 on Mac OS X 10.6.
I just compiled and ran the following program incorporating your code:
#import <Foundation/Foundation.h>
int main() {
int max_size = 20;
int h[max_size];
h[0] = 5;
NSLog(#"It is %d", h[0]);
return 0;
}
It worked fine. The problem is something besides simply declaring an array.
This was with GCC 4.0.1 on Mac OS X 10.4.
If I recall correctly, some compilers need to know the size of stack-allocated arrays explicitly at compile-time. This (possibly) being the case, you could make your max_size variable const or an #define macro (or an integer literal, as you've done.) Alternatively, you could dynamically allocate the array and then the size could be any-old variable
ex:
int *array = calloc(max_size, sizeof(int));

Xcode print symbol not found for my C function which used in Objective-C method body

Xcode build prints this error .
Undefined symbols:
"EGViewportDimensionMake(unsigned int,
unsigned int, unsigned int, unsigned
int)", referenced from:
-[Renderer render] in Renderer.o ld: symbol(s) not found collect2: ld
returned 1 exit status
I cannot figure out what's the problem. I'm not good at classic C syntax.
These are the function source code files:
EGViewportDimension.h
#import <Foundation/Foundation.h>
struct EGViewportDimension
{
NSUInteger x;
NSUInteger y;
NSUInteger width;
NSUInteger height;
};
typedef struct EGViewportDimension EGViewportDimension;
EGViewportDimension EGViewportDimensionMake(NSUInteger x, NSUInteger y, NSUInteger width, NSUInteger height);
EGViewportDimension.m
#import "EGViewportDimension.h"
EGViewportDimension EGViewportDimensionMake(NSUInteger x, NSUInteger y, NSUInteger width, NSUInteger height)
{
EGViewportDimension dim;
dim.x = x;
dim.y = y;
dim.width = width;
dim.height = height;
return dim;
}
I referenced and used this like:
Renderer.mm
#import "EGViewportDimension.h"
//.... many codes omitted.
EGViewportDimension vdim = EGViewportDimensionMake(0, 0, backingWidth, backingHeight);
This is not a compiler but a linker issue. You referenced this method from [Renderer render], however the linker is unable to find it. Did you check you have included EGViewportDimension.h at the appropriate place (eg. Renderer.m)?
I solved it by renaming Renderer.mm to Renderer.m.
It was used some C++ classes so I made it as Objective-C++ code, but there was some problem.
I removed all C++ calls and renamed it to Objective-C code.
But I still don't know what's the problem with Objective-C++ with classic C function definition.
----(edit)----
I asked this as another question, and I got an answer. See here:
Does it prohibited calling classic C function from Objective-C++ class method body?