Types
Kauhiz

This is something I never learned, when I studied C, so be patient with me. I'd like to make a type called ENEMY to create an enemy easily. Now I know I should make the type like this:

typedef struct ENEMY{
     int x,y;
     int state;
}

I could then create a enemy by ENEMY *enemy1; But how do I read and change the variables? Also, please correct me, if I said something stupid...

Steve Terry

Fist off you only create a pointer.. you need to malloc an enemy for that.

enemey1 = malloc(sizeof(struct ENEMY));

enemy1->x = 10;
enemy1->y = SCREEN_H >> 1;
enemy1->state = ENEMY_ALIVE;

Hrvoje Ban

Or you can make function to do it:

ENEMY *create_enemy(int new_x, int new_y, int new_state)
{
  ENEMY *tmp = malloc(sizeof(struct ENEMY));
  tmp->x = new_x;
  tmp->y = new_y;
  tmp->state = new_state;

  return tmp;
}

ENEMY *enemy1 = create_enemy(100, 100, ENEMY_ALIVE);

Oscar Giner

The syntax for the ENEMY struct is not correct. It should be:

typedef struct ENEMY{
     int x,y;
     int state;
} ENEMY;

You can create enemies by two ways:

statically:

{
    ENEMY enemy1;

    enemy1.x = 0;
    enemy1.x = 560;
    enemy1.state = 0;
}
// enemy1 does not longer exist, after the closing }

or

dinamically:

{
    ENEMY *enemy1;

    enemy1 = (ENEMY *)malloc(sizeof(ENEMY));

    enemy1->x = 0;  // equivalent to (*enemy).x = 0
    enemy1->x = 560;
    enemy1->state = 0;

    free enemy;  // destroys the enemy1 data.
}
// if you don't call free enemy1 is still in memory and can be accesed by anyone who knows its memory address (pointer).

ReyBrujo

You create a new type with the keyword typedef. You declare a new variable of some time on the fly with only the keyword struct:

typedef struct node_st {
    int data;
    struct node_st *next;
} node_t;

struct list_st {
    node_t *first;
    node_t *last;
} list;

/*  list is a variable, node_t is a type  */

spellcaster

I also highly recommand the use of calloc to create data for structs, since it will fill the memory with zeros.
Also, you shouldn't use ALL_CAPS for a type, since that's norally used for constant values only.

Yves Rizoud

Just a precision aboout one item:

typedef struct ENEMY
{
     int x,y;
     int state;
} ENEMY;

Kauhiz may not see it clearly why the word ENEMY appears twice.. in this precise case, the top one is unneeded. It's a kind of 'temporary' identifier, which is valid only until the struct is defined (until the } ENEMY; )
ReyBrujo shows one case where it's needed:

typedef struct node_st {
    int data;
    struct node_st *next;
} node_t;

This is a classic node element for a linked list of ints.
"next" is meant to be a pointer to a node_t, but the word "node_t" is not yet defined while the compiler parses the struct (it's farther down in the code) So you give a temporary name (node_st) at the beginning, and define "next" as a pointer to node_st.

If it's clear....

edit:
no CAPS? While learning C, I usually saw typedef structs in uppercase from books and sample code, though I cant really remember the origin... Well, it's a matter of norma. If you never succumb to the evil macros demons, uppercase is free for this use, right? ;D

X-G

(going somewhat off topic)

Quote:

Also, you shouldn't use ALL_CAPS for a type, since that's norally used for constant values only.

Most seasoned programmers know that this is true. Yet, Allegro has BITMAP * and a whole bunch of other things along the same line. Should that be dealth with, you think?

spellcaster

Allegro is code he can't influence. He can influence the code he writes, though :)

And I think that BITMAP and SAMPLE started as macros, which are the other case where you's ude ALL_CAPS.

EDIT:

Quote:

If you never succumb to the evil macros demons, uppercase is free for this use, right? ;D

Constants != macros.
While you can use the preprocessor for macros, it's better to use enums.

enum {
   I_AM_A_CONSTANT = 120,
   I_AM_A_CONSTANT_AS_WELL = 300
};

X-G

No, what I mean is... shouldn't Allegro's types be fixed? It's inevitable that newbs who get hold of Allegro code start believing that since Allegro does it, it's standard and they should too. Shouldn't Allegro use a better naming system to teach the right way to handle types?

spellcaster
Quote:

No, what I mean is... shouldn't Allegro's types be fixed?

Maybe, but this is not the right place to discuss that. But I guess you could suggest this on [AD] or the allegro-development board of this forum.

X-G

That's why I said I was going off-topic. ;) Okay, back to where we were. Uhm, wasn't the question answered already?

Johan Halmén

How about

struct Enemy
{
  int x,y;     
  int state;
};

or is this pure C++?

X-G

In C, you would have to create a variable by doing "struct Enemy alien;". In C++, just "Enemy alien;" is enough.

Tobias Dammers
spellcaster said:

Also, you shouldn't use ALL_CAPS for a type, since that's normally used for constant values only.

I think this discussion is quite idle. I myself use ALL_CAPS for all types I define, and all_lowercase for instances. Since I work in C++ most of the time, this means that a class is in caps, and a class instance in lower case. I don't consider this "wrong" or "not done", but rather a convention, just as valid as others as long as you stick to it.
And, by the way, allegro is not the only API using it; the win api does pretty much the same thing, except for that evil Hungarian stuff. Anyway, as far as I'm concerned, I say let people name their identifiers the way they want to.
And X-G, please be so good and read the part of the allegro doc about "hacking allegro" or something like that. Shawn (I think it was him) defined the allegro code style there in detail, and AFAIK all the allegro code follows these rules neatly. Which means there is actually nothing to be fixed, unless by "fix" you mean "rewrite the library to fit your own coding style" (no offence pal).

X-G

Quote:

"rewrite the library to fit your own coding style

I do, because it's not just my coding style. It's the coding style of 90% of all C developers out there. Just because Shawn decided to use that nomenclature for Allegro doesn't make it a good thing.

Oscar Giner

And that 90% of people use a nomenclature, doesn't mean it's the good one :P

As long as you are coherent with your nomenclature, use whatever you want. Like if you want to use MiXeD cAsE, but do it in all your code (then you'll find that mixed case is not very optimal;)).

In C I use usually use capitalization in my projects for structs, like Enemy. This leaves me the enemy word free for other usage :)

ReyBrujo

I suffix types with _t, structures with _st, constants in uppercase, if bit positions WHATITISABOUT_I_NAME, if definitions (max something in example) WHATITISABOUT_D_NAME, if enums WHATISITABOUT_E_NAME, if a macro WHATITISABOUT_M_NAME. Constants are prefixed with CONST_WHATITISABOUT. Then I use lowercase for everything else. Easy for me to search all values with _t , _st , _D_, _I_, _E_, _M_ or CONST_ :)

X-G

Quote:

And that 90% of people use a nomenclature, doesn't mean it's the good one

No, but it's self-consistent and consistent with how it was done, so there's really no good reason to use anything else for no added benefit. The style with UPPERCASE_MACROS_WITH_UNDERSCORES is universally recognizable.

Yves Rizoud

still off-topic...

X-G said:

It's the coding style of 90% of all C developers out there

Not in my part of the world. C developers here have always been using uppercase typedef structs :the whole Allegro library (BITMAP, RGB, PALETTE) but it dates back to the libc library itself (or FILE is a constant ?)

X-G

Yes, Allegro uses it, but that's what we're discussing so you can't exactly use it as an example, heh. As for libc...

Yes, FILE is uppercase, and I don't know why. I can't find any other libc typedefs that are: time_t, size_t, sockaddr etc are all lowercase. Then again I'm not looking that closely. Feel free to prove me wrong.

Derezo

Meh. It's personal taste. I'd never in my wildest dreams write something like this:

   while (joy[0].flags & JOYFLAG_CALIBRATE) {
      if (calibrate_joystick(0) != 0) {
   set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
   allegro_message("Error calibrating joystick!\n");
   return 0;
      }
   }

Found in exjoy.c.

I'd write that like so:

  while (joy[0].flags & JOYFLAG_CALIBRATE)
   {
    if (calibrate_joystick(0) != 0)
     {
      set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
      allegro_message("Error calibrating joystick!\n");
      return 0;
     }
   }

Neither way is wrong. It's personal taste, just like using caps for structures.

Personally, I use ALL_CAPS for both classes and macro's. Wouldn't have it any other way.

X-G

Of course neither way is "wrong" in the strictest sense. I just believe, and so does many, many others (the majority, I wager), that sticking to conventions like UPPERCASE_MACROS is a good idea for code legibility. I think that should be encouraged.

Richard Phipps

And I'd write it like this:

  while (joy[0].flags & JOYFLAG_CALIBRATE)
  {
   if (calibrate_joystick(0) != 0)
   {
    set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
    allegro_message("Error calibrating joystick!\n");
    return 0;
   }
  }

Evert

And I'd write it as it is now, but with eight real spaces instead of one tab as Allegro's code uses.

Personally, I use uppercase names for defines and typedefs. I think that's how it was done in the book I read for the C programming course I followed. I like it.

Oscar Giner
Quote:

Yes, FILE is uppercase, and I don't know why. I can't find any other libc typedefs that are: time_t, size_t, sockaddr etc are all lowercase

But time_t, size_t, sockaddr are typedefs to basic types. Maybe FILE is the only struct in the libc?

If you look at WinAPI, all structs and typedefs are uppercase.

SDL uses SDL_CapitalizedCase.

FMod uses FMOD_OPTIONALSUBSYSTEM_CapitalizedCase. And FMOD_SOMETHINGCALLBACK for callback typedefs.

So no, structs and typedef don't have a standard. ALL_UPPERCASE for macros is the only one that's standard.

X-G

First off, sockaddr is not a typedef to a basic type, it is a struct. And there are many more structs in libc.

Even though structs and typedefs don't have a standard, it might be a good idea to make sure they at least aren't exactly the same as macros. It becomes a bit hard to tell them apart at a glance.

Derezo

If you see something like this:

DATA_TYPE myData;

Whether or not DATA_TYPE is a class/struct makes absolutely no difference to how it is used. It could be a macro, it could be a struct. Doesn't even matter, because it doesn't change it's use at all.

memset(myData, 0, sizeof(DATA_TYPE));Same idea.

There's very few instances where it really matters.

spellcaster

I must admit that I use the sun java coding rules for all projects I'm allowed to use my preferred coding style.
MixedCase for everything but constants which are UNDERLINE_SEPARATED. Types start Uppercase, variables start lowercase.

typdef struct {
   int foo;
} Foo;

Foo foo;

if (foo.foo == 0) {
    foo.foo = 5;
} else {
    foo.foo = 0;
}

Yves Rizoud
Quote:

ALL_UPPERCASE for macros is the only one that's standard

Well, I checked libc, it's not very consistent... Between getc() and fgetc(), one is a macro, one is a function, and they put them all in lowercase.

Well I think everything has been said... All standards exist and are used and misused. Personnally, at home I use whichever I feel best, but professionnally I'll follow whatever standards are set for the current project. Nothing is worse than 4+ stubborn programmers using their own preferred variant of standards and notations... :)

Evert
Quote:

Between getc() and fgetc(), one is a macro, one is a function, and they put them all in lowercase.

Some libc functions are implemented both as functions and as macros. This is true of the isalpha() family of functions too. The reason is historical, for compilers that did not inline functions as a modern compiler does.

HoHo

I generally use Java coding style also. It just looks so nice, clean and readeable.

Tobias Dammers

I find it annoying to have constants in ALL_CAPS, for a simple reason: When I make a program, at certain points constants may become variables. The way I work, this happens fairly often. And the only real difference between variables and constants is, well, that little "const" keyword. But in using them, there is no reason why they should use different nomenclatures.
Anyway, I say everbody just use their system and be happy with it. Only when you have a team project, it becomes important to have rules and stick with them.
And, once again to X-G: Allegro has a valid, sensible and coherent nomenclature. There is absolutely no reason to change it, except that it doesn't fit your personal taste. Which basically means that if you don't like Allegro, go re-write it yourself.

X-G

Dammers: First of all, I am not forcing anyone to do anything. You really do not have to use that attitude towards me or anyone else. I am merely suggesting that types should be lowercase and macros uppercase, to make it more clear which is which, and to be more conformant with the rest of the world. This is not about taste. It is a clear, objective improvement to be able to tell them apart easily. Maybe you don't consider it important enough, but that's not the same as it being up to personal taste.

Tobias Dammers

Let's see if I got this right:
Allegro nomenclature:
Macros, constants and types are ALL_CAPS
Variables and functions are all_lower_case
You want:
Macros are constants are ALL_CAPS
Variables, functions and types are all_lower_case

So you get a way to tell types from macros, but lose a way to tell types from variables. One clear objective improvement won, one lost. Averages to zero, meaning matter of personal taste.

The most important thing to tell from each other, I'd say, are macros and functions. Next would be variables and constants, though not as important. The rest is fairly easy to tell anyway from the way things are being used. Nobody uses a type as a variable, and if they do, the compiler will warn or fail. And macros are seldomly used like types, which is why it is totally unnecessary to add a way of telling which is which.

[edit]
btw.: it has been stated more than once in this thread that not the whole "rest of the world" uses your system. Allegro (obviously) doesn't, neither do windows, OpenGL, SDL, Java, or libc.

X-G

There are ways to distinguish types from variables that doesn't require one of them to occupy the same slot as macros. Either do MixedCase types, or suffix them with _t.

EDIT: Not the whole world. But a lot of it. Your examples represent very few libraries, in fact, and as for the ones that do... Libc is confused, as stated (it uses both uppercase and lowercase types). OpenGL? What types does that have that are uppercase? AFAIK, they're all on the style of "GLuint". Java uses uppercase constants, and MixedCase types, so that supports MY position if anything.

Tobias Dammers

You're totally right there, but that still doesn't mean allegro should be changed. Nothing big will be won, but nearly all compatibility and those allegro users who got used to the current system will be lost.
Also, I would like you to read my posts more carefully. After re-reading mine, I noticed that I didn't use the word "force" (or any of its synonyms) at all, yet you accuse me of saying you wanted to force people to do anything. And the reason why I was showing a bit of an attitude here is that after your suggestion was rejected by a majority here, you just repeated that things "should" be changed. Repeating something doesn't make it more right. People who do that sometimes succeed nevertheless, just because they shout the loudest and the longest, and that annoys me a bit.

X-G

You definitely made it sound like I was trying to force my opinion on them. If you had acknowledged it as a suggestion, you would not have used such harsh language. Also, a majority thinking something does not make it "right" either, just as little as repeating it makes it right.

Whenever I repeat myself, I do so in order to refute further arguments from them. I am not just blindly repeating my original statement, and I take offense at you suggesting that I do.

Now, compatibility IS an issue. But, as we all know, we are on the verge of an API change. Now if any is the right time to bring up issues like this, so that we don't make the same mistakes in the future versions of Allegro.

Tobias Dammers

I see your point. Do you see mine?

X-G

If your point is that a change to the current API is more or less impossible for practical reasons, yes.

Tobias Dammers

Almost. My point is that a change to the current API is not only more or less impossible for practical reasons, but also quite pointless, as the current nomeclature is both useful and coherent. In spite of your arguments, I don't see any advantage in changing it the way you suggest.

X-G

The advantage is quite clear: The ability to tell macros apart from types at a glance. Your argument that types then become indistinguishable from variables is invalid, since you can just use MixedCase for types, or suffix them with _t.

Tobias Dammers

I can tell macros and types at a glance in allegro as well. No need to spell differently.

X-G

That is simply because you have experience with Allegro and know what's a macro and what's a type. But consider if you one day ran across this:

a = AMBIGUOUS_CONSTRUCT();

Is this an object being created? Is it a macro being invoked and possibly having harmful side effects and then returning some kind of error code? How would you know? Meanwhile, if it was named AmbiguousConstruct (or ambiguous_construct_t), you would know it was a class/type and shouldn't have the normal macro caveats in it.

Tobias Dammers
Quote:

a = AMBIGUOUS_CONSTRUCT();

In C++, it should be a class, because in C++, using macros can and should be avoided.
In C, it's probably a macro, definitely not a type.

Here's mine:

a = sizeof(ambiguous_thing);

Is ambiguous_thing a type or a variable?

X-G

Quote:

In C, it's probably a macro, definitely not a type.

In C (barring the parentheses, which can be removed and it would really be the same) that could very well be a type. Allegro does it, after all.

Quote:

Is ambiguous_thing a type or a variable?

If you've used a consistent scheme and named your types either "AmbiguousThing" or "ambiguous_thing_t", then that must be a variable. If not, you still have a problem and need to distinguish types from variables (and I have now suggested ways to do so three times).

Thomas Fjellstrom
Quote:

And I'd write it as it is now, but with eight real spaces instead of one tab as Allegro's code uses.

Ack! Hard tabs all the way, and NO spaces. Don't care what tabs are set to in the coders editor, since I can change it to that in mine, but I don't like looking at the mess that is allegro's mess of tabs and spaces.

HoHo

macros, consts: ALL_CAPS
types, classes: MixedCase
variables: mixedCase <- no upper case in first letter.

This is the way I do and I distinguish all of them from each other by just looking at their name

nonnus29
typedef struct ENEMY{
    int x,y;
    int state;
    ENEMY* enemy;
    ENEMY* myfriend;
} ENEMY;

ENEMY* createEnemy(ENEMY* _enemy) {
    ENEMY* temp = malloc(sizeof(ENEMY));
    temp->enemy = _enemy;
    temp->myfriend = _enemy->enemy;
    return temp;
}

Tobias Dammers

I'm tired of wasting my time discussing complete non-issues like this one. Having read earlier threads involving X-G, I should have known the outcome right from the start anyway.

Korval

The key issue is this: do you consider Macros to be dangerous?

If you do not, then there is little problem with having Macros and types (structs/typedefs/etc) use the same conventions.

However, if you consider macros to be dangerous (and there's considerable evidence for this), then having a specific convention that separates macros immediately from any other section in the code is quite desireable.

Thread #397198. Printed from Allegro.cc