Differenct between a Struct and Typedef


#1

Just going by the examples in the book I cant really tell the difference between a struct and a typedef. The book says that you can pass a typdef to another function by refering the name of the typdef.

From what I can see what is the reason why you could not just pass the data in the struct by refering to the name of the struct?

I guess I am wondering why use typdef?

Thanks


#2

A typedef is where you give an existing type a new name. For example, if you liked to use “elephant” instead of “int”, you could typedef it:

typedef int elephant;
Now you can use elephant any where you would have used int:

elephant x; x = 3;

struct enables you to make a new type comprising old types. Like, lets say you wanted a new type made up of two floats.

[code]struct point {
x float;
y float;
};

struct point center;
center.x = 3.4;
center.y = 4.5;[/code]


#3

Ok. So why would I want to use elephant instead of int? Im still struggling with this.

The book says “A typedef defines an alias for a type declaration and allows us to use it more like the usual data types.”

I looked at the original BMICalc program and compared it to the one using typdef.I dont see a reduction in the amount of code I need. and as shown below I am able to use Struct the same way that the example uses typedef. I wish there was an extra sentence here that gave an example or reason to back up the statement.

the book goes on to say. “Now that you have created a typedef, you can pass a Person structure to another function.”

In the code below I was able to pass a Person structure to another function and I did not use typedef. So what is the advantage?

As with pointers I feel I cant continue until I understand this topic.

[code]#include <stdio.h>

// Here is the declatation of the struct Person

struct Person{
float heightInMeters;
int weightInKilos;

};

float bodyMassIndex(struct Person p){
return p.weightInKilos / (p.heightInMeters * p.heightInMeters );

}

int main (int argc, const char * argv[])
{
struct Person mike;

mike.weightInKilos = 96;
mike.heightInMeters = 1.8;

float bmi = bodyMassIndex(mike);

printf("Mike has a bmi of %.2f\n", bmi);

// printf(“Mike weighs %i kilograms\n”, mike.weightInKilos);
// printf(“Mike is %.2f meters tall\n”, mike.heightInMeters);

return 0;

}[/code]

Thanks.


#4

Understanding typedef is not as important as understanding pointers, so I think you can continue learning without having a firm grasp. If you want more information about typedef right this minute, there are many explanations that a simple Google search will reveal. Try “c typedef description.” Here is one to get you started: http://stackoverflow.com/questions/252780/why-should-we-typedef-a-struct-so-often-in-c


#5

You make an excellent point that using elephant instead of int seems useless. It’s not until you start needing to do slightly more complex things that the usefulness of typedef starts to shine through.

Consider this example, from one of Apple’s headers, NSObjCRuntime.h:

#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64 typedef long NSInteger; typedef unsigned long NSUInteger; #else typedef int NSInteger; typedef unsigned int NSUInteger; #endif

This code looks at several things that may or may not have been #define’d in other headers, imported above this snippet. Those headers #define the processor architecture of the machine that you’re building for.

Note, though, that we see this #if / #else / #endif. All of these statements that start with the hash symbol (#) are called preprocessor directives, and we won’t worry about them for now. You should be able to guess what these ones in particular do.

This particular set conditionally typedefs NSInteger to be an int or an unsigned int depending on the computer’s processor architecture.

This is because an int can be a 4-byte number or a 2-byte number depending on the computer. The difference can cause all sorts of problems if you’ve used int throughout your program, and then compile it for a different kind of computer where int may no longer be a sufficiently large type to store the numbers you need.

By conditionally using typedef to make NSInteger be either an int or a long int depending on your computer’s architecture, NSInteger becomes a numerical type that you can use safely for almost all architectures, without worrying about whether you might accidentally be compiling for a computer where a normal int isn’t big enough.

The more common uses of typedef are are typically in conjunction with struct and enum declarations, but I wanted to provide this example in hopes that it helps to understand why typedef can be a useful command in and of itself.


#6

I am trying to see what the difference is between using a struct and a typedef struct.

Is it that with struct, any time you are initializing it, you have to rewrite the word struct in that line of code, as in the example of the book p. 65?

struct Person person;

And with a typedef struct, you don’t (as in the book p.66)?

Person person;

Is there more to it than that, like the scope of one being bigger than the other one: typedef struct on a wider scope than just struct?


#7

A “typedef struct” and a “struct” are not two distinct types.

“Typedef” isn’t a modifier or an adjective or a noun. It’s a command that allows you to assign something like a nickname or alias to an existing type.

It’s usually used to make more complex types like structs and enums take fewer keystrokes on your keyboard to use.

When we say:

typedef struct { float heightInMeters; int weightInKilos; } Person;

we’re using a command whose invocation looks like this:

where sometype is an existing type, such as a struct, and nickname is the nickname we want to use to refer to sometype in the future. This way, if sometype is annoying to type in, I can just use its nickname:

instead of:

At this stage, the typedef command does nothing more than save you some extra keyboard typing later on in your program. By taking a longer type name “struct Person” and making it shorter: “Person”


#8

Type names or aliases are a bit like pointers. They can be considered “compile-time pointers to actual types: they point to actual types.” If someone changes an object to which you have a pointer, you will see the changes in the object. If a piece of code is using a type name for an actual type and if someone changes the “value” (namely the actual type) of the type name, then the change will be automatically reflected in that piece of code at compile time.

To see this consider:

// MyTypes.h - Version 1 (sorry, discrete values only)

typedef unsigned int mass_type;
typedef unsigned int speed_type;
typedef unsigned int energy_type;

And:

// Physics.h

#import "MyTypes.h"

energy_type Energy (mass_type, speed_type);
...

// Physics.c

#import "Physics.h"

energy_type Energy (mass_type m, speed_type v)
{
   return 0.5 * (m * v * v);
}
...

Now consider this change:

// MyTypes.h - Version 2 (continuum of values)

typedef float mass_type;
typedef float speed_type;
typedef float energy_type;

With the Version 2 of MyTypes.h, there is no need to change the files Physics.h and Physics.c. This would not have been possible, if the actual types had been used in those files.

Also, as a bonus, judiciously defined type names can make the code more readable.


#9

[quote=“MikeyWard”]A “typedef struct” and a “struct” are not two distinct types.

“Typedef” isn’t a modifier or an adjective or a noun. It’s a command that allows you to assign something like a nickname or alias to an existing type.

It’s usually used to make more complex types like structs and enums take fewer keystrokes on your keyboard to use.


Thanks. That makes sense.