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
Vanadium
Jan 8, 2005

Smackbilly posted:

Tbe biggest advantage is that enums are typesafe, so you will not need that extra "assert" statement to check that the parameter is in the valid range. If you have:

room->link(0, Direction(14));

:(

Adbot
ADBOT LOVES YOU

Smackbilly
Jan 3, 2001
What kind of a name is Pizza Organ! anyway?

Vanadium posted:

room->link(0, Direction(14));

:(

Well there what you're doing is performing a type-unsafe C-style cast. If you go around doing that, all the type-safety in the world isn't going to help you, since you're basically telling the compiler "I know better than you do here; shut up". And if you actually don't know better...

By the way, regarding the "counting the valid enums" problem, here's how I usually handle it:

code:
struct Directions {
  enum Direction { North, South, East, West };
  const unsigned int NUMDIRECTIONS = 4;
};
This has the effect of keeping both the enumerated values and the counter constant inside their own namespace, so you refer to "Directions::North" instead of just "North", which allows you to use the symbol "North" elsewhere without conflict. Plus, if you're consistent about naming, you'll know that the type Foos::Foo will always have an associated Foos::NUMFOOS constant that you can use.

Smackbilly fucked around with this message at 13:04 on Jun 5, 2008

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
Why do you use a struct declaration instead of a namespace?

more falafel please
Feb 26, 2005

forums poster

floWenoL posted:

On the other hand, it introduces an invalid value (kNumWhatever) that is treated like a valid value.

Plus GCC on overly paranoid settings will complain if you do this:
code:
enum Direction { North, South, East, West, kNumDirections };

void DoWork(Direction dir)
{
    switch (dir)
    {
        case North:
            DoNorthWork();
            break;
        case South:
            DoSouthWork();
            break;
        case East:
            DoEastWork();
            break;
        case West:
            DoWestWork();
            break;
    }
}
warning: enumeration value kNumDirections not handled in switch

But you should be putting default: blocks in switch anyway.

That Turkey Story
Mar 30, 2003

I haven't tested it thoroughly, but I just put together a little macro for simple, safe enums if anyone wants it. You need boost installed to use it (header only). I only compiled with VC++ 9 but it should be portable unless I made a poopie, which is probably pretty likely. Right now, enums must be created at namespace scope, but with some effort, that can be changed.

To make a simple direction type that has north, south, east, and west constants and that default constructs to north, use:

code:
SAFE_ENUM( direction, (north)(south)(east)(west), north )
To make a simple direction type with optional initialized constants (note the additional parenthesis):

code:
SAFE_ENUM_WITH_VALUES( other_direction, ((north)) ((south)(6)) ((east)(15)) ((west)), north )
Construction and assignment can only be done via copies or by one of the above constants. There is also no implicit conversion to the enum's promoted type:

code:
// Assuming the above macro invocation...
direction a = direction::east,
          b = a,
          c = direction::default_value,
          d;
To access the value of a constant as a valid compile-time integral constant (useful for switch cases and metaprogramming):

code:
// Again, assuming the above macro invocation...
direction::value_of::north
To access the value of an instance of your enum at runtime, use:

code:
some_instance_of_your_enum.value();
To access the number of constants that were specified use:

code:
// Note, the value of the expression is not a valid direction itself.
// It is also a valid compile-time constant expression that can be used,
// for example, as an array size.
your_enum_type::amount_of_constants

That Turkey Story fucked around with this message at 01:59 on Jun 6, 2008

floWenoL
Oct 23, 2002

Mustach posted:

Why do you use a struct declaration instead of a namespace?

Because not everyone programs in C++.

Smackbilly
Jan 3, 2001
What kind of a name is Pizza Organ! anyway?

floWenoL posted:

Mustach posted:

Why do you use a struct declaration instead of a namespace?

Because not everyone programs in C++.

Actually the real reason is because you can't declare a namespace inside a class. So if I want to do something like this:

code:
class Foo {
public:
  struct States {
    enum State { Initiailzed, InProgress, Aborted, Completed };
    static const unsigned int NUMSTATES = 3;
  };
};
To get the effect of having a Foo::States namespace, the only option is to use a struct (or a class, but why have an extra "public:" line?).

Smackbilly fucked around with this message at 16:26 on Jun 6, 2008

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
That makes sense, thanks.

floWenoL posted:

Because not everyone programs in C++.
He could only have been talking about C++. In C, declaring an enumeration inside of a struct doesn't offer the same benefits as in C++ — the enum types and constants are all still in the same namespace, as if they were outside of the struct:
code:
struct S{
  enum E{ Hi };
};

struct T{
  enum E{ /* error: redeclaration of ‘enum E’ */
    Hi    /* error: redeclaration of enumerator ‘Hi’ */
  };
};

int main(void){
    enum E e; /* Works if one of the above structs is deleted */
    return 0;
}

Vanadium
Jan 8, 2005

Also you cannot have a static const NUMDIRECTIONS field in C.

Smackbilly
Jan 3, 2001
What kind of a name is Pizza Organ! anyway?
This is more a gcc question, but:

Is there a way to force gcc to link in everything from a static library, even if you're not using it?

The context is that I want to create a shared library libfoo.so which uses libbar.a, and I want EVERYTHING in libbar.a to be available to programs which link against libfoo.so without having to have libbar available.

The problem is that there can be programs which use symbols in libbar.a which are not used by libfoo.so, so by default these symbols are not included in libfoo.so when it statically links against libbar.a.

litghost
May 26, 2004
Builder

Smackbilly posted:

This is more a gcc question, but:

Is there a way to force gcc to link in everything from a static library, even if you're not using it?

The context is that I want to create a shared library libfoo.so which uses libbar.a, and I want EVERYTHING in libbar.a to be available to programs which link against libfoo.so without having to have libbar available.

The problem is that there can be programs which use symbols in libbar.a which are not used by libfoo.so, so by default these symbols are not included in libfoo.so when it statically links against libbar.a.

gcc is really just a front to some other utilities. The one that controls linking is "ld", and the option you need to pass to it is "-E", I think (source). You can use "-Xlinker option" with gcc to pass the flag to the linker (source), or call ld yourself, passing in the object files to make into a .so. There is probably a direct gcc flag, but I didn't see it.

floWenoL
Oct 23, 2002

Mustach posted:

That makes sense, thanks.
He could only have been talking about C++. In C, declaring an enumeration inside of a struct doesn't offer the same benefits as in C++ — the enum types and constants are all still in the same namespace, as if they were outside of the

You're absolutely right; I don't know what I was thinking.

Paniolo
Oct 9, 2007

Heads will roll.
What's the most elegant way for a class to expose a collection? At the very least, it needs add, remove, and enumeration faculties. Preferably it shouldn't be tied to any particular container type, either. I've run up against this pattern a few times and haven't found any particularly elegant solution.

That Turkey Story
Mar 30, 2003

Paniolo posted:

What's the most elegant way for a class to expose a collection? At the very least, it needs add, remove, and enumeration faculties. Preferably it shouldn't be tied to any particular container type, either. I've run up against this pattern a few times and haven't found any particularly elegant solution.

Could you elaborate more on your situation? Before you decide to directly expose the container, make sure you can't just represent your functionality as higher-level operations that are internally implemented with a container. If the encapsulating class holds the container but all the manipulation is still done directly by users rather than indirectly through the class, then your type is likely just a low-level aggregate (which is okay depending on your situation, think std::pair or tuple types) or it is a container itself (which again is okay).

In the case of it being an aggregate, you can always just directly expose your object rather than making a redundant interface. If it's a container itself, the easiest way to make your type a compliant container without an is-a relationship is to privately inherit from the container you are using and then promote the interface elements to public with using. From your brief description, it sounds to me like you are in more of the latter case. If you feel as though your type is neither of these things, then try to tell more details about what you are doing.

slovach
Oct 6, 2005
Lennie Fuckin' Briscoe
I decided I'd try goofing a bit of GDI tonight, so I decided to make a starfield.

It pretty much works, except I don't know how to repaint the window. If I drag it all over, it updates fine, which is basically the effect I need, because right now it's just moving the stars but since it's not redrawing anything, I'm just getting streaks.

RedrawWindow sounded right enough, but apparently I'm stupid and it's not doing anything.
code:
RedrawWindow(hwnd, 0, 0, RDW_INVALIDATE);
:confused:

tyrelhill
Jul 30, 2006
Look up InvalidateRect.

slovach
Oct 6, 2005
Lennie Fuckin' Briscoe

tyrelhill posted:

Look up InvalidateRect.

Thanks. :)

Shoes
Dec 19, 2007
As a project for a systems class, I need to write a sequential-logging proxy in C. But I can't manage to get a piece of code to submit a valid HTML request. The following just hangs for a second, and prints a blank string. The same request submitted using telnet gives me google's home page.

What am I doing wrong?

(The Rio stuff is a set of robust/buffered IO functions we've been given to use for the class. The professor has used them before, so I'm going to guess they're not the issue. Rio_readn reads n characters, Rio_readinitb sets up a buffer for an rio struct / file descriptor pair, and Rio_readlineb reads lines from the buffer, refilling the buffer as it goes.)

code:
int main(int argc, char **argv) 
{
    int clientfd, port;
    char *host, buf[MAXLINE];
    char *request = "GET [url]http://www.google.com/[/url] HTTP/1.1 \r\n";
    rio_t rio;
  
    host = "www.google.com";
    port = 80;

    clientfd = Open_clientfd(host, port);
    Rio_readinitb(&rio, clientfd);

    Rio_writen( clientfd, request, strlen(request));
    Rio_readlineb(&rio, buf, MAXLINE);
    Fputs( buf, stdout );

    Close(clientfd);
    exit(0);
}

Smackbilly
Jan 3, 2001
What kind of a name is Pizza Organ! anyway?

Shoes posted:

What am I doing wrong?

code:
    char *request = "GET [url]http://www.google.com/[/url] HTTP/1.1 \r\n";

HTTP requests need to end with a blank line (because there can be multiple lines in a single request). Stick another \r\n on the end and you should be fine.

Shoes
Dec 19, 2007

Smackbilly posted:

HTTP requests need to end with a blank line (because there can be multiple lines in a single request). Stick another \r\n on the end and you should be fine.

D'oh! Thanks!

slovach
Oct 6, 2005
Lennie Fuckin' Briscoe
Another GDI question.

The more I use it, the more I notice that SetPixel is slow as hell. What's a faster way to draw?

Hubis
May 18, 2003

Boy, I wish we had one of those doomsday machines...

slovach posted:

Another GDI question.

The more I use it, the more I notice that SetPixel is slow as hell. What's a faster way to draw?

What are you drawing? Any primitive draw function (line, circle, etc) or (ideally) bitmap blitting is going to be a lot faster overall, due to hardware acceleration.

slovach
Oct 6, 2005
Lennie Fuckin' Briscoe

Nuke Mexico posted:

What are you drawing? Any primitive draw function (line, circle, etc) or (ideally) bitmap blitting is going to be a lot faster overall, due to hardware acceleration.

Thanks, I started using a DIB and speed gain is enormous, probably well over 10x in extreme cases. A little confusing since I basically had to make my own equivalent of SetPixel, but well worth it.

ColdPie
Jun 9, 2006

While reading through the Qt documentation the other day, I noticed that they use a simple strategy to get around the include file mess that we talked about that in here a few months ago. I don't remember seeing it mentioned when we talked about this, and it seems like a pretty nice solution.

code:
/*SomeClass.h*/
#ifndef SomeClass_h
#define SomeClass_h

class SomeClass
{
public:
  SomeClass(int blah);
  //whatever...
};

#endif
code:
/*Another.h*/
#ifndef Another_h
#define Another_h

//note that there's no include, we just say "this
//class exists," kind of like a function prototype
class SomeClass; 

class Another
{
public:
  Another();
  SomeClass someClass;
  //whatever...
};

#endif
code:
/*Another.cpp*/
#include "Another.h"

//here's where we include the actual header
#include "SomeClass.h"

Another::Another():
  someClass(17)
{
  //whatever...
}

//implement functions, etc.
I've never seen this strategy used before -- is there a disadvantage to it? Using this strategy, changing SomeClass.h won't cause everything that depends on Another.h to recompile, which is what I considred to be the major problem with the "include mess."

ColdPie fucked around with this message at 05:12 on Jun 12, 2008

cronio
Feb 15, 2002
Drifter
It's called a forward declaration. It's used all over the place -- it's the standard way of removing the include file mess.

Note that it only works on pointers or references, where the compiler doesn't need to know the full definition of the object.

So:
code:
class SomeClass;

SomeClass* asdf;
works, but:

code:
class SomeClass;

SomeClass asdf;
does not

[edit]
FYI forward declaring classes/structs in headers saves a huge amount of compile time in large code bases. Seeing code that includes unnecessary headers in other headers makes me seethe with rage.

Also, if what you're trying to forward declare is inside a namespace, you can do:
code:
namespace A
{
  class B;
}

A::B* asdf;

cronio fucked around with this message at 05:16 on Jun 12, 2008

ehnus
Apr 16, 2003

Now you're thinking with portals!
Forward declarations will only work for pointers or references, where the compiler doesn't need to figure out the size of the type. In your "Another" class, it will have to contain either a pointer or reference to SomeClass. It's a pretty common usage pattern

ColdPie
Jun 9, 2006

I see, thanks for the tip. Hopefully someone in here hasn't seen it before and thinks it's as awesome as I do :)

TSDK
Nov 24, 2003

I got a wooden uploading this one
For reference, it's commonly called the 'pimpl idiom' in C++, and more generally known as an 'opaque pointer':
http://en.wikipedia.org/wiki/Opaque_pointer

TheBlackRoija
May 6, 2008
I'm trying to run a relay off a serial port on windows using code I found here
(not the one included in the article, the one found about 1/4 of the way down the page)

when I try to compile it a get a whole bunch of "'WORDS' undeclared (first use in this function)" errors

My programming experience comes entirely from a university course I took a couple years ago where we made C programs to do basic calculations, read/write text files and not much else...so I'm a little over my head dealing with this kind of stuff

What do I need to do to make this work?

Smackbilly
Jan 3, 2001
What kind of a name is Pizza Organ! anyway?

TheBlackRoija posted:

when I try to compile it a get a whole bunch of "'WORDS' undeclared (first use in this function)" errors

Please post the exact error messages.

csammis
Aug 26, 2003

Mental Institution

TheBlackRoija posted:

when I try to compile it a get a whole bunch of "'WORDS' undeclared (first use in this function)" errors

Tell us what compiler you're using, what OS (and version) you're compiling on, and copy-paste the exact errors you're getting.

Wuen Ping
Feb 2, 2007

cronio posted:

It's called a forward declaration. It's used all over the place -- it's the standard way of removing the include file mess.

Note that it only works on pointers or references, where the compiler doesn't need to know the full definition of the object.

So:
code:
class SomeClass;

SomeClass* asdf;
works, but:

code:
class SomeClass;

SomeClass asdf;
does not

This is true for aggregation of objects in classes, but interestingly you can use forward declaration to define function parameters that you intend to pass by copy (you don't need to make them references or pointers):

code:
// header
class Foo;

#define DEFINE_BAR 0 // set to 1 if you like error messages
#if DEFINE_BAR
class Bar
{
public:
    Foo m_foo;
};
#endif

void UseFoo(Foo f);

class Foo
{
public:
    int One() const { return 1; }
};

// implementation
int main()
{
#if DEFINE_BAR
    Bar bar;
#endif

    UseFoo(Foo());

    return 0;
}

void UseFoo(Foo f)
{
    f.One();
}
Note that the declaration of UseFoo occurs before the definition of Foo, and the first call to UseFoo happens before its definition. This is all fine.

chutwig
May 28, 2001

BURLAP SATCHEL OF CRACKERJACKS

I'm having an issue with a program I'm writing in C that's supposed to talk to our database servers for periodic status updates. Here's the offending code section that I'm having problems with:
code:
active_query_t *curr_q = (active_query_t *)malloc(sizeof(active_query_t));
		
if(curr_q == NULL)
{
    perror("Unable to allocate memory for curr_q.\n");
    PQfinish(sa_dbconn);
    exit(1);
}

curr_q->datid = strtol(PQgetvalue(db_activity, i, PQfnumber(db_activity, "datid")), NULL, 10);
curr_q->procpid = strtol(PQgetvalue(db_activity, i, PQfnumber(db_activity, "procpid")), NULL, 10);
curr_q->current_query = g_string_new(PQgetvalue(db_activity, i, PQfnumber(db_activity, "current_query")));
curr_q->backend_start = g_string_new(PQgetvalue(db_activity, i, PQfnumber(db_activity, "backend_start")));
curr_q->datname = g_string_new(PQgetvalue(db_activity, i, PQfnumber(db_activity, "datname")));

strptime(PQgetvalue(db_activity, i, PQfnumber(db_activity, "backend_start")), "%Y-%m-%d %H:%M:%S", curr_q->bs_tm);
curr_q->bs_time_t = mktime(curr_q->bs_tm);

curr_q->notified = FALSE;
curr_q->hash_len = get_hash(curr_q->hash->str, curr_q->current_query, curr_q->backend_start);
This executes inside a for loop that scans all the result rows from the query.

The problem that I'm having seems to be a problem with allocating memory. sizeof(active_query_t) returns 80, which seems too small, since this is the definition of the struct:
code:
gint64 datid;
gint32 procpid;
GString *current_query;
GString *backend_start;
GString *datname;
time_t bs_time_t;
struct tm *bs_tm;
gboolean notified;
GString *hash;	
gint32 hash_len;
gint64 is 8 bytes, gint32 is 4 bytes, GString is 24 bytes, time_t is 8 bytes, tm is 56 bytes, gboolean is 4 bytes. If I add these all up myself, I get 180 bytes.

Whatever's going on, it's causing real problems for me. If I malloc() the memory (as in the code example above), the code always crashes when trying to set curr_q->bs_time_t. If I use g_slice_alloc() instead, the code crashes even earlier when setting the value of curr_q->bs_tm in strptime().

I'm not really sure where to begin with this, since I don't see any obvious errors in my handling of allocating memory. I tried allocating 4*sizeof(active_query_t) just to see if that would help, but it continues to crash. None of the code before the time handling code crashes, but it will either crash in there or in get_hash if I comment out the time handling code. Setting curr_q->notified never crashes.

EDIT: this is on Linux (Debian unstable AMD64) with gcc 4.3.

chutwig fucked around with this message at 17:06 on Jun 12, 2008

TSDK
Nov 24, 2003

I got a wooden uploading this one

chutwig posted:

The problem that I'm having seems to be a problem with allocating memory. sizeof(active_query_t) returns 80, which seems too small, since this is the definition of the struct:
code:
gint64 datid;
gint32 procpid;
GString *current_query;
GString *backend_start;
GString *datname;
time_t bs_time_t;
struct tm *bs_tm;
gboolean notified;
GString *hash;	
gint32 hash_len;
gint64 is 8 bytes, gint32 is 4 bytes, GString is 24 bytes, time_t is 8 bytes, tm is 56 bytes, gboolean is 4 bytes. If I add these all up myself, I get 180 bytes.
current_query et al are pointers to GString objects, likewise bs_tm is a pointer to a tm struct.

I'd recommend reading chapter 5 of K&R for starters.


EDIT: Your current crash is because bs_tm is an uninitialsed pointer to a random bit of memory that you're then trying to write to, but if you don't understand pointers then you're going to run into yet more problems real soon.

TSDK fucked around with this message at 17:35 on Jun 12, 2008

TheBlackRoija
May 6, 2008

csammis posted:

Tell us what compiler you're using, what OS (and version) you're compiling on, and copy-paste the exact errors you're getting.

Nevermind, I'm just retarded, no <>'s around the filenames...
..and I changed "void main" to "int main" with the return 0 at the end

Although now that the program works I don't think it's doing what I'm trying to get,
whether or not the program is run I get -10V across the pins and I should be getting +10 after..
got this now too

Anyone have experience running circuits off of serial ports?

I'm using Dev-C++ and running XP btw

now I'm just wondering if there is a way I can trigger this off an existing program, either by closing itself or by breaking an infinite loop...or any other way I don't have the knowhow to have thought of. The program does 2 things when this one should be triggered, transmits data through the serial port and plays a sound...

TheBlackRoija fucked around with this message at 20:56 on Jun 12, 2008

chutwig
May 28, 2001

BURLAP SATCHEL OF CRACKERJACKS

TSDK posted:

current_query et al are pointers to GString objects, likewise bs_tm is a pointer to a tm struct.

I'd recommend reading chapter 5 of K&R for starters.


EDIT: Your current crash is because bs_tm is an uninitialsed pointer to a random bit of memory that you're then trying to write to, but if you don't understand pointers then you're going to run into yet more problems real soon.

Okay, I understand my first mistake; forgetting that the pointer is its own type with a different size from what it points to.

That being said, I guess I need to issue a malloc for bs_tm and then have it write to that, and probably also malloc the other pointers before I write to them.

I know I don't completely understand pointers yet; that's why I'm undertaking this now, so that I become more aware of manual memory management rather than simply letting the computer always do it for me. Just telling somebody to read K&R again doesn't help much when dealing with something like pointers that is very complex.

chutwig fucked around with this message at 18:41 on Jun 12, 2008

Thug Bonnet
Sep 22, 2004

anime tits ftw

chutwig posted:

Okay, I understand my first mistake; forgetting that the pointer is its own type with a different size from what it points to.

Yeah, you're getting confused between the pointer's value versus the value of what it's pointing at. The pointer just contains an address (4 bytes worth) of a location in memory. That location in memory is hopefully something useful (a variable, for instance). Remember that the pointer is not the value of that variable, it's just a reference to it. You can change what it's pointing at at any time.

For example:
code:
#include <stdio.h>

struct data{
	int foo;
	float bar;
	long baz;
};

int main(){
	printf(
		"\nDeclare an int variable and a pointer to an int, then we set the int pointer to the address of ('&') the int variable.\n\n"
		);

	int i, *ip;
	ip = &i;

	i = 10;
	printf("Value of i: %d\n", i);
	printf("Location of i in memory: %#X\n", ip);

	printf(
		"\nLet's change the value of i by dereferencing pointer ip by using the '*' operator\n\n"
		);

	*ip = 12;
	printf("Value of i: %d\n", i);
	printf("Value of i (via dereferencing our pointer): %d\n", *ip);

	struct data dataVar;
	struct data * dataPointer;

	printf(
		"\nThe same is true of structs\n\ndataVar size: %d\ndataPointer (pointer) size: %d\ndataPointer (value) size: %d\n", 
		sizeof(dataVar), sizeof(dataPointer), sizeof(*dataPointer)
		);
	return 0;
}

Mikey-San
Nov 3, 2005

I'm Edith Head!

quote:

The pointer just contains an address (4 bytes worth) of a location in memory.

The size of a pointer is architecture-dependent. Under 32-bit, a pointer is 4 bytes; on 64-bit, a given memory location is 8 bytes long.

Thug Bonnet
Sep 22, 2004

anime tits ftw

Mikey-San posted:

The size of a pointer is architecture-dependent. Under 32-bit, a pointer is 4 bytes; on 64-bit, a given memory location is 8 bytes long.

True! :)

Adbot
ADBOT LOVES YOU

more falafel please
Feb 26, 2005

forums poster

chutwig posted:

Okay, I understand my first mistake; forgetting that the pointer is its own type with a different size from what it points to.

That being said, I guess I need to issue a malloc for bs_tm and then have it write to that, and probably also malloc the other pointers before I write to them.

I know I don't completely understand pointers yet; that's why I'm undertaking this now, so that I become more aware of manual memory management rather than simply letting the computer always do it for me. Just telling somebody to read K&R again doesn't help much when dealing with something like pointers that is very complex.

The biggest problem people generally have with learning pointers is that they're told "oh yeah, pointers are hard, that's why I hate C," and then they believe it's some horrible convoluted thing.

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