27 Apr, 2009, boblinski wrote in the 1st comment:
Votes: 0
I recently switched from using Cygwin on my own Windows XP machine, to a server (ISUnlimited)..

I copied over my mud to the server and did a "make clean"/"make".

I got these warnings when I "make" 'd:
Quote
gcc -Wall -O -ggdb -DNOCRYPT -DQMFIXES -c -o obj/db.o db.c
db.c: In function 'do_dump':
db.c:3350: warning: format '%8d' expects type 'int', but argument 4 has type 'long unsigned int'
db.c:3368: warning: format '%8d' expects type 'int', but argument 4 has type 'long unsigned int'
db.c:3368: warning: format '%d' expects type 'int', but argument 6 has type 'long unsigned int'
db.c:3377: warning: format '%8d' expects type 'int', but argument 4 has type 'long unsigned int'
db.c:3377: warning: format '%d' expects type 'int', but argument 6 has type 'long unsigned int'
db.c:3388: warning: format '%8d' expects type 'int', but argument 4 has type 'long unsigned int'
db.c:3388: warning: format '%d' expects type 'int', but argument 6 has type 'long unsigned int'
db.c:3400: warning: format '%8d' expects type 'int', but argument 4 has type 'long unsigned int'
db.c:3417: warning: format '%8d' expects type 'int', but argument 4 has type 'long unsigned int'
db.c:3417: warning: format '%d' expects type 'int', but argument 6 has type 'long unsigned int'
db.c:3426: warning: format '%8d' expects type 'int', but argument 4 has type 'long unsigned int'
db.c:3426: warning: format '%d' expects type 'int', but argument 6 has type 'long unsigned int'
db.c:3430: warning: format '%8d' expects type 'int', but argument 4 has type 'long unsigned int'
db.c:3434: warning: format '%8d' expects type 'int', but argument 4 has type 'long unsigned int'


I did not get these warnings when I was using Cygwin..

This is the code it is refering to:
top_mob_index, top_mob_index * (sizeof (*pMobIndex)));		/*line 3350*/

/* mobs */
count = 0;
count2 = 0;
for (fch = char_list; fch != NULL; fch = fch->next)
{
count++;
if (fch->pcdata != NULL)
num_pcs++;
for (af = fch->affected; af != NULL; af = af->next)
aff_count++;
}
for (fch = char_free; fch != NULL; fch = fch->next)
count2++;

fprintf (fp, "Mobs %4d (%8d bytes), %2d free (%d bytes)\n",
count, count * (sizeof (*fch)), count2,
count2 * (sizeof (*fch))); /*line 3368*/

/* pcdata */
count = 0;
for (pc = pcdata_free; pc != NULL; pc = pc->next)
count++;

fprintf (fp, "Pcdata %4d (%8d bytes), %2d free (%d bytes)\n",
num_pcs, num_pcs * (sizeof (*pc)), count,
count * (sizeof (*pc))); /*line 3377*/

/* descriptors */
count = 0;
count2 = 0;
for (d = descriptor_list; d != NULL; d = d->next)
count++;
for (d = descriptor_free; d != NULL; d = d->next)
count2++;

fprintf (fp, "Descs %4d (%8d bytes), %2d free (%d bytes)\n",
count, count * (sizeof (*d)), count2, count2 * (sizeof (*d))); /*line 3388*/

/* object prototypes */
for (vnum = 0; nMatch < top_obj_index; vnum++)
if ((pObjIndex = get_obj_index (vnum)) != NULL)
{
for (af = pObjIndex->affected; af != NULL; af = af->next)
aff_count++;
nMatch++;
}

fprintf (fp, "ObjProt %4d (%8d bytes)\n",
top_obj_index, top_obj_index * (sizeof (*pObjIndex))); /*line 3400*/


/* objects */
count = 0;
count2 = 0;
for (obj = object_list; obj != NULL; obj = obj->next)
{
count++;
for (af = obj->affected; af != NULL; af = af->next)
aff_count++;
}
for (obj = obj_free; obj != NULL; obj = obj->next)
count2++;

fprintf (fp, "Objs %4d (%8d bytes), %2d free (%d bytes)\n",
count, count * (sizeof (*obj)), count2,
count2 * (sizeof (*obj))); /*line 3417*/

/* affects */
count = 0;
for (af = affect_free; af != NULL; af = af->next)
count++;

fprintf (fp, "Affects %4d (%8d bytes), %2d free (%d bytes)\n",
aff_count, aff_count * (sizeof (*af)), count,
count * (sizeof (*af))); /*line 3426*/

/* rooms */
fprintf (fp, "Rooms %4d (%8d bytes)\n",
top_room, top_room * (sizeof (*room))); /*line 3430*/

/* exits */
fprintf (fp, "Exits %4d (%8d bytes)\n",
top_exit, top_exit * (sizeof (*exit))); /*line 3434*/


Is there a need to fix this error? If so what exactly should I be looking at?

Thanks.
28 Apr, 2009, Kline wrote in the 2nd comment:
Votes: 0
It's complaining about your fprintf statements. See this link for more info on printf format specifiers: http://www.cppreference.com/wiki/c/io/pr...
28 Apr, 2009, Banner wrote in the 3rd comment:
Votes: 0
Did you try changing all the 'long unsigned int' to 'int' like it says?
28 Apr, 2009, boblinski wrote in the 4th comment:
Votes: 0
Where and what do I change to INT exactly?
28 Apr, 2009, Banner wrote in the 5th comment:
Votes: 0
The defines in your main header file, mud.h, merc.h. Whatever the main definitions file is.
28 Apr, 2009, Lancsta wrote in the 6th comment:
Votes: 0
# /* exits */
# fprintf (fp, "Exits %4d (%8d bytes)\n",
# top_exit, top_exit * (sizeof (*exit)));


You know I had the same issue before, compiling on a mac. I had changed to
# /* exits */
# fprintf (fp, "Exits %4d (%8ld bytes)\n",
# top_exit, top_exit * (sizeof (*exit)));

Which resolved the issue, but now compiling under linux I get

db.c:2760: warning: format '%8ld' expects type 'long int', but argument 4 has type 'unsigned int'
28 Apr, 2009, David Haley wrote in the 7th comment:
Votes: 0
Waitwaitwait, don't change your data structures or variable types, that is likely to break a lot of other things.

Do what Kline said and fix the printf format specifiers to match the type.
28 Apr, 2009, elanthis wrote in the 8th comment:
Votes: 0
In particular, use %ld or %8ld as appropriate for anything of type long int. Use %lu or %8lu as appropriate for anything of type unsigned long int.

Technically the warnings don't matter at all (a long int and an int are identical in size/layout for 32-bit Intel architecture machines, and the unsigned and signed only matters for integers >= 2^31), but if you ever compile on a 64-bit non-Windows machine, that code will break six ways to Sunday. Definitely don't change types everywhere, though. Just fix the printf() formats to be correct.
28 Apr, 2009, Lancsta wrote in the 9th comment:
Votes: 0
Yeah I didn't think I had to change the structures at all. I had an idea it was in the printf, I wasn't aware of %lu though, that's some good info :) Thanks for the input.
28 Apr, 2009, boblinski wrote in the 10th comment:
Votes: 0
Okay, thanks for the everyones input so far.. just trying to get my head around this…

I'll focus on line 3368:

Quote
db.c:3368: warning: format '%8d' expects type 'int', but argument 4 has type 'long unsigned int'
db.c:3368: warning: format '%d' expects type 'int', but argument 6 has type 'long unsigned int'


The code is..
fprintf (fp, "Mobs    %4d (%8d bytes), %2d free (%d bytes)\n",
count, count * (sizeof (*fch)), count2,
count2 * (sizeof (*fch))); /*line 3368*/


So it says in the warning… expects 'int'… but the data is actually 'long unsigned int'.. therefore something needs changed from a '%d' type to a '%lu' type.. correct?

How do I know which are the 4th and 6th arguments?
28 Apr, 2009, David Haley wrote in the 11th comment:
Votes: 0
Not trying to be facetious: just count commas. fp is the first, the string is the second, and so on.
28 Apr, 2009, Kline wrote in the 12th comment:
Votes: 0
Correct. Your arguments are (inside the quotes) every %<something>, ie, %4d, %8d, etc. Outside the quotes they are just enumerated to match 1:1 within whatever function you call (fprintf, here), comma delimited. So argument 1 is your fp, argument 2 is everything within the quotes, your string, argument 3 is your count variable, argument 4 is count * (sizeof (*fch)) and so on.
28 Apr, 2009, boblinski wrote in the 13th comment:
Votes: 0
Alright, so I would change that particular section of code to look like:

fprintf (fp, "Mobs    %4d (%8lu bytes), %2d free (%lu bytes)\n",
count, count * (sizeof (*fch)), count2,
count2 * (sizeof (*fch))); /*line 3368*/
28 Apr, 2009, Kline wrote in the 14th comment:
Votes: 0
Yep, that should work fine.
29 Apr, 2009, Banner wrote in the 15th comment:
Votes: 0
I liked my idea better.
29 Apr, 2009, Tyche wrote in the 16th comment:
Votes: 0
Banner said:
I liked my idea better.


fprintf (fp, "Mobs %4d (%8d bytes), %2d free (%d bytes)\n",
count, count * int(sizeof (*fch)), count2,
count2 * int(sizeof (*fch)));

I like my idea above even better. ;-)
29 Apr, 2009, David Haley wrote in the 17th comment:
Votes: 0
Banner, I'm not sure if you're being facetious, but your solution is actually wrong. If you use the wrong format specifier in printf, you don't change your data to conform to the format specifier, you change the format specifier to conform to the data. Or, you do something like what Tyche suggested and cast appropriately. But you certainly don't change the types – incidentally, that isn't what the error message was saying to do.
29 Apr, 2009, Banner wrote in the 18th comment:
Votes: 0
I was being sarcastic. But I thought I remembered having to change the data type when you go from 32-bit to 64-bit or something. I'm sure thats what I did when I got an error that looked similar to that.
29 Apr, 2009, elanthis wrote in the 19th comment:
Votes: 0
Banner said:
I was being sarcastic. But I thought I remembered having to change the data type when you go from 32-bit to 64-bit or something. I'm sure thats what I did when I got an error that looked similar to that.


You don't need to change data types if your code is written properly. A lot of poorly written code uses int and long interchangeably, which it shouldn't – they're different types for a reason. In most 32-bit systems int and long both end up 32-bits, but in *some* 64-bit systems long ends up being 64-bit while int stays 32-bit, making them no longer interchangeable in certain cases (as assigning from a long to an int can result in lost data). Windows 64-bit still treats long as 32-bit which, while annoying, at least helps drive home the point that you can't just make random assumptions about the size of a data type. In general, use int everywhere unless you specifically know you need a smaller or larger size, and when that case arises, the safest bet is to use one of the types from stdint.h/inttypes.h.

One of C++'s many strengths over C of course is that this printf crap is easily replaced with with iostreams (which are easier to teach I've found, even if iostreams impose a lot of limitations) or something like Boost.format which has all the strengths of printf without the stupid type issues.
29 Apr, 2009, quixadhal wrote in the 20th comment:
Votes: 0
Or you can do what I tend to do, and that's use "int" everywhere unless there's a very specific reason not to. One hopes you can trust your compiler to make the default "integer" size the proper one for your architecture's most efficient use. For example, on a 32-bit platform, addressing is typically aligned by 32-bit words, so accessing a "short int" has to fetch the same memory as an "int", and then internally mask/shift it to return you the 16-bit value.

If I win the lotto and upgrade to a 64-bit system, all my "integers" still work. Anywhere that I expected bit-shifting or rotating to roll around at 32-bit boundaries, I hopefully commented and did my best to use sizeof().

Learning about structure padding and alignment pretty much removed my desire to use the smallest type possible. If I really need that level of efficiency, I'll bite the bullet and do it in assembly myself.
0.0/28