Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Contains Acetone
Aug 22, 2004
DROP IN ANY US MAILBOX, POST PAID BY SECUR-A-KEY

Contains Acetone fucked around with this message at 17:39 on Jun 24, 2020

Adbot
ADBOT LOVES YOU

MrMoo
Sep 14, 2000

Plorkyeran posted:

10 seconds on a 30 minute build with msvc.

Importantly: 10 seconds slower with #pragma once.

xgalaxy
Jan 27, 2004
i write code
I don't really care myself which one is faster, I just wish they would standardize #pragma once and move on. The #ifdef include guards are cumbersome and error prone. I can't believe an elegant, one line solution like #pragma once is even a debate. All the poo poo they added to C++ 11 and they couldn't make this essential part of developing programs just a little bit easier is baffling.

Someone submit a proposal for C++ 14 please.

xgalaxy fucked around with this message at 02:40 on May 11, 2013

floWenoL
Oct 23, 2002

MrMoo posted:

Importantly: 10 seconds slower with #pragma once.

We might be looking at two different runs, but the original data that drove the inclusion of #pragma once was a ~1 minute speedup with it on Visual Studio.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
The #ifndef variant provides a convenient escape-hatch if there's some case where you really do want to re-include the header, which you can't do with #pragma once. So if you've got one of those cases in your codebase then you've got to either use include guards everywhere, or have this one file that does things completely different to the rest of your codebase.

MrMoo
Sep 14, 2000

xgalaxy posted:

The #ifdef include guards are cumbersome and error prone.

The two reasons for removal from Chromium are firstly it being more error prone, and secondly not being faster.

The "original data" for inclusion of #pragma once could not be reproduced and ends up a show piece for cargo culting.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

MrMoo posted:

cargo culting

I'll take "phrases that nobody actually uses correctly" for 400, Alex.

xgalaxy
Jan 27, 2004
i write code
I'd love to see a real world example where #pragma once is error prone that isn't a result of a compiler bug.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Jabor posted:

The #ifndef variant provides a convenient escape-hatch if there's some case where you really do want to re-include the header, which you can't do with #pragma once. So if you've got one of those cases in your codebase then you've got to either use include guards everywhere, or have this one file that does things completely different to the rest of your codebase.
Or you could just not do that, since I can't think of any case where it would be legal to include a header twice yet sensible to have include guards that doesn't involve doing something incredibly stupid.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Plorkyeran posted:

Or you could just not do that, since I can't think of any case where it would be legal to include a header twice yet sensible to have include guards that doesn't involve doing something incredibly stupid.

One example would be where you have some file containing message definitions. Some other header file uses those to generate function declarations for stuff to do with the messages, while the corresponding implementation file uses them to generate definitions for those functions.

The message definition file needs to be doubly-included in that particular implementation file, but should still be guarded for everywhere else.

Bonfire Lit
Jul 9, 2008

If you're one of the sinners who caused this please unfriend me now.

MrMoo posted:

The two reasons for removal from Chromium are firstly it being more error prone, and secondly not being faster.
It's just more error-prone if you're that one guy from their mailing list who doesn't understand what inclusion guards are.

Dicky B
Mar 23, 2004

If you're making errors while typing out an include guard then stop using computers

That Turkey Story
Mar 30, 2003

Dicky B posted:

If you're making errors while typing out an include guard then stop using computers

Or use an IDE that will create them for you.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

Jabor posted:

One example would be where you have some file containing message definitions. Some other header file uses those to generate function declarations for stuff to do with the messages, while the corresponding implementation file uses them to generate definitions for those functions.

The message definition file needs to be doubly-included in that particular implementation file, but should still be guarded for everywhere else.

Uh? What you're doing sounds like X-Macros, and you can't really just include an X-Macros header at random. What's a concrete example when you imagine this?

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Suspicious Dish posted:

Uh? What you're doing sounds like X-Macros, and you can't really just include an X-Macros header at random. What's a concrete example when you imagine this?

When the header containing the message definitions also contains typedefs for various types used in the message, and you're explicitly including all headers that you rely on instead of depending on them being transitively included somewhere (which is a good idea for other reasons).

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
That was a good concrete example. I love the double-definition of typedefs that surely won't end in an error.

Hughlander
May 11, 2005

Only thing I could remotely think of would be something I saw awhile back that wouldn't use include guards *OR* pragma once:

File.h:
code:
FOO(first),
FOO(second),
FOO(third),
FOO(fourth)
code:
#define FOO(x) ##x
enum things
{
#include "file.h"
};

#undef FOO
#define FOO(x) x
char *ThingsStr[] = {
#include "file.h"
};
#undef FOO

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
While we're on this subject, is there a standard naming convention for include-guards to prevent library headers from fighting project headers?

I've occasionally felt in danger of having a library that does a #define _FOO_H_ for one of its headers and then having a header file with the same name in the main project, which would result in whichever one of the two is included second not getting included at all, which would be horrific to debug if it happened by surprise.

Dicky B
Mar 23, 2004

Hughlander posted:

Only thing I could remotely think of would be something I saw awhile back that wouldn't use include guards *OR* pragma once:

File.h:
code:
FOO(first),
FOO(second),
FOO(third),
FOO(fourth)
code:
#define FOO(x) ##x
enum things
{
#include "file.h"
};

#undef FOO
#define FOO(x) x
char *ThingsStr[] = {
#include "file.h"
};
#undef FOO
I don't think that fits the scenario in question:

Jabor posted:

The message definition file needs to be doubly-included in that particular implementation file, but should still be guarded for everywhere else.
In your example there is no need to guard at all.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

Hughlander posted:

Only thing I could remotely think of would be something I saw awhile back that wouldn't use include guards *OR* pragma once:

Yeah, this is known as "X-Macros", and normally doesn't have any include guards.

Dicky B
Mar 23, 2004

roomforthetuna posted:

While we're on this subject, is there a standard naming convention for include-guards to prevent library headers from fighting project headers?

I've occasionally felt in danger of having a library that does a #define _FOO_H_ for one of its headers and then having a header file with the same name in the main project, which would result in whichever one of the two is included second not getting included at all, which would be horrific to debug if it happened by surprise.
I think the onus is on the library writer to do something sensible like _LIBRARYNAME_FOO_H.

Rottbott
Jul 27, 2006
DMC

Dicky B posted:

If you're making errors while typing out an include guard then stop using computers
I've seen it when someone copy-pasted a header to get started and forgot to change it. It is a nightmare to debug and can hide for years until someone includes something in a particular order. That's why I use only #pragma once. (It's also much less ugly.)

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Jabor posted:

One example would be where you have some file containing message definitions. Some other header file uses those to generate function declarations for stuff to do with the messages, while the corresponding implementation file uses them to generate definitions for those functions.

The message definition file needs to be doubly-included in that particular implementation file, but should still be guarded for everywhere else.

I would file that under "incredibly stupid". Just split the things that need to be doubly-included into a separate file that isn't include-guarded rather than being ~clever~.

FamDav
Mar 29, 2008

Suspicious Dish posted:

That was a good concrete example. I love the double-definition of typedefs that surely won't end in an error.

But defining the same typedef twice doesn't result in an error.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

FamDav posted:

But defining the same typedef twice doesn't result in an error.

http://codepad.org/sU0wPJlo ?

That Turkey Story
Mar 30, 2003

Dicky B posted:

I think the onus is on the library writer to do something sensible like _LIBRARYNAME_FOO_H.

Don't start with an underscore. Global names that begin with _ are reserved (also names that begin with _ followed by a capital letter are reserved everywhere, and so are names that contain a double underscore).

MrMoo
Sep 14, 2000

roomforthetuna posted:

While we're on this subject, is there a standard naming convention for include-guards to prevent library headers from fighting project headers?

The Chromium project uses directory names as a prefix, separated by underscores. Example:

http://src.chromium.org/svn/trunk/src/base/atomicops_internals_atomicword_compat.h

#ifndef BASE_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_

FamDav
Mar 29, 2008

Sorry, I thought yall were talking about C++ for some reason.

EDIT: though it's going to work like C++ in C11, apparently.

FamDav fucked around with this message at 20:31 on May 11, 2013

MrMoo
Sep 14, 2000

Suspicious Dish posted:

I'll take "phrases that nobody actually uses correctly" for 400, Alex.

It's cargo cult copying when you see poo poo like this:

code:
#ifndef blaa_h_
#define blaa_h_

#ifdef _MSC_VER
#pragma once
#endif
...

Vinterstum
Jul 30, 2003

MrMoo posted:

Importantly: 10 seconds slower with #pragma once.

I can't speak for Chromium (yet), but our internal codebase at work did show a small improvement (MSVC; we didn't test GCC) with #pragma once. Not much more than 1% of the total clean build time, but hey everything helps.

floWenoL
Oct 23, 2002

MrMoo posted:

It's cargo cult copying when you see poo poo like this:

code:
#ifndef blaa_h_
#define blaa_h_

#ifdef _MSC_VER
#pragma once
#endif
...

That's not actually how #pragma once was used in Chromium. ??:(

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


On my current compiler and architecture, chars are 8-bit, shorts are 16-bit, ints and pointers are 32-bit, long longs and doubles are 64-bit, and floats/longs/pointers are 32 or 64 depending on whether I'm compiling in 32-bit or 64-bit.

Are these sizes consistent or guaranteed in any way across modern compilers/architectures? Sorry, I'm sure this is an obvious question, but I'm not really sure what to google for. :(

Ciaphas fucked around with this message at 00:38 on May 15, 2013

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
The standards only guarantee minimum sizes, and not necessarily useful minimum sizes at that. However, practically speaking, char will always be eight bits, short will be 16, int will be 32, and long long will be 64. long is not portable across architectures or compilers. The floating-point types are generally portable except on weird systems (not including long double).

However, to the extent that you care about exact sizes, you should be using typedefs like uint32_t.

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


Buggery. I knew about things like size_t but had no idea there were typedefs for precisely-sized definitions like that. It's terrible how much basic stuff I don't know, I hesitate to imagine how much of my code would end up in the Horrors thread if it had the chance. :(

Oh well, thanks much.

FamDav
Mar 29, 2008
Well what are you doing that requires this kind of information?

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


Lots and lots (and lots) of what amounts to file format conversions, basically. It's all worked so far since we've only targeted one platform (namely, ours--SunCC/SunOS/SPARC) but with the eventual (like, 2+ years out) move to g++/Linux/Intel I've been checking out possible portability issues left and right, and this one occurred to me suddenly.

Morham
Jun 4, 2007
I have a quick question regarding some logic I have written. It's my first C program, and it's a guess the number game in the console. I wrote the following code to prompt the player if they wanted to play again, and to continually do so until they either typed 'y' (121) or 'n' (110).

code:
do								
{
	printf("Would you like to play again? (y/n): ");
	scanf("%s", &input);
}
while (input != 121 && input != 110);
Now when I first wrote this I used an 'OR' ('||') operator in the while condition thinking that would be right since I want it to continue to ask until the player hits 'y' or 'n' however it didn't work. When I replaced it with an 'AND' ('&&') operator it works perfectly. In my mind this operation should continue until input is equal to 121 and 110 at the same time, and since a variable can't hold two values it should never stop executing.

Am I misunderstanding something fundamental about logic here?

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Morham posted:

I have a quick question regarding some logic I have written. It's my first C program, and it's a guess the number game in the console. I wrote the following code to prompt the player if they wanted to play again, and to continually do so until they either typed 'y' (121) or 'n' (110).

code:
do								
{
	printf("Would you like to play again? (y/n): ");
	scanf("%s", &input);
}
while (input != 121 && input != 110);
Now when I first wrote this I used an 'OR' ('||') operator in the while condition thinking that would be right since I want it to continue to ask until the player hits 'y' or 'n' however it didn't work. When I replaced it with an 'AND' ('&&') operator it works perfectly. In my mind this operation should continue until input is equal to 121 and 110 at the same time, and since a variable can't hold two values it should never stop executing.

Am I misunderstanding something fundamental about logic here?

What's the difference between
code:
input != 121 && input != 110
and
code:
!(input == 121 || input == 110)

nielsm
Jun 1, 2009



The do..while loop continues until the condition becomes false.

The != operator is false when the operands are equal.

The || operator is false only when both operands are false.

If input!=121 is false then input must be equal to 121, and then input!=110 can't also be false. Therefore your condition with || could never become false.

Another thing, use character constants instead of numeric constants. You can write input!='y' and get the same behavior as with input!=121, but the former is much clearer about your intention. Remember that character constants (single characters enclosed in single quotes) are a fancy way of writing integer constants, but express different intentions to a human reader.

Lastly, a good rule to learn is this:
If X and Y are boolean expressions, then !(X&&Y)==(!X||!Y), and conversely !(X||Y)==(!X&&!Y).
(It has a name which I forgot.)

Adbot
ADBOT LOVES YOU

Jewel
May 2, 2009

Also please don't use magic numbers.

C++ code:
!(input == 'n' || input == 'y')

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply