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
WorldIndustries
Dec 21, 2004

Can anyone recommend any good sources of C documentation or tutorials? I'm going through Learn C the Hard Way but many things are left deliberately up to the reader to figure out.
I have K&R as well, but something more modern would be nice.

Adbot
ADBOT LOVES YOU

weird
Jun 4, 2012

by zen death robot
C Programming: A Modern Approach is really good, and covers C99.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Hughlander posted:

Go -Weverything or go home. (Clang only.)

Note that clang does have a lot of opt-in warnings for people who want to enforce some project-specific convention — like not auto-synthesizing properties in Objective-C — so if you're going to roll with -Weverything, don't feel bad about opting back out of specific things.

shrughes
Oct 11, 2008

(call/cc call/cc)
I view -Weverything as a tool for discovering new warnings you'd like to enable.

YO MAMA HEAD
Sep 11, 2007

I'm working with algorithmic audio generation at the bit level (see http://countercomplex.blogspot.com/2011/10/some-deep-analysis-of-one-line-music.html for details). Basically, you take a (bitwise-manipulation heavy) equation with one variable t that gets incremented at the sample rate. The solution gets cast to a char, so you're working with a max of 256. What I'm interested in knowing is when a pattern will repeat—for example, the equation t*(42&t>>10) gives a phrase 65536 samples long, as does t&t>>8. Obviously, the trivial case of t will repeat after 256 samples, while equations like t|t%255|t%257 take much longer.

I see two options—somehow analyzing the equation (once) for its periodicity or doing some kind of running comparison (this could even be fuzzy). Any thoughts?

The code will eventually be running on an Arduino at 8000hz, so it'd be nice if there were a fast/inexpensive way to do this.

InAndOutBrennan
Dec 11, 2008
The below works fine as long as I keep it in my main but as soon as I try to move it to a function it leads to not being able to bind to the statement further down.

The work I try to do:

code:
sqlite3_stmt *sql_insert_stmt;

std::string query_str = "INSERT INTO test VALUES(";
for(unsigned long long i = 0; i < num_columns; ++i) {
	query_str += "?, ";
}
query_str.resize(query_str.size()-2);
query_str += ")";

rc = sqlite3_prepare_v2(sqldb
			,query_str.c_str()
			,-1
			,&sql_insert_stmt
			,NULL);

if(rc != SQLITE_OK) {
	std::cout << "Could not prepare" << std::endl;
}
Code would just be copied pasted in to the function below with small changes in varnames and added return statements.

code:
int create_insert_statement(sqlite *sqldb, sqlite3_stmt *sql_stmt, int num_columns) {
...
}
And called with (sqldb and num_columns are intialized earlier):
code:
sqlite3_stmt *sql_insert_stmt;
create_insert_statement(sqldb, sql_insert_stmt, num_columns);
Guesses:
1. I'm not preparing the statement I think I'm preparing when I pass the pointer to the sqllite3_stmt? SQLite is not complaining so far though.
2. If not the above then it's something to do with the statement needing to remember the query text and that goes out of scope when the function exits. This would mean that it working for me is purely coincidental since I'm reusing the same std::string multiple times.

InAndOutBrennan fucked around with this message at 12:50 on Dec 30, 2012

nielsm
Jun 1, 2009



As far as I can guess, you aren't correctly passing the sqlite3_stmt out of the function. (You didn't provide the actual code of the function, instead giving a puzzle missing some of the pieces.)

Either just return it as a plain return value (and throw an exception on error), or use the same mechanism as the sqlite3_prepare_v2 function by passing in a pointer to a pointer. (Alternatively, a reference to a pointer.)


C++ code:
// passing in a pointer-to-pointer
int create_insert_statement(sqlite *sqldb, sqlite3_stmt **sql_stmt, int num_columns) {
  std::string query_str = "INSERT INTO test VALUES(";
  for(unsigned long long i = 0; i < num_columns; ++i) {
    query_str += "?, ";
  }
  query_str.resize(query_str.size()-2);
  query_str += ")";

  rc = sqlite3_prepare_v2(sqldb
                         ,query_str.c_str()
                         ,-1
                         ,sql_stmt
                         ,NULL);

  if(rc != SQLITE_OK) {
    std::cout << "Could not prepare" << std::endl;
  }
}

// call site
int main() {
  sqlite *db;
  sqlite3_stmt *stmt;
  create_insert_statement(db, &stmt, 5);
}
C++ code:
// returning as a plain value
sqlite3_stmt * create_insert_statement(sqlite *sqldb, int num_columns) {
  sqlite3_stmt *statement = NULL;

  std::string query_str = "INSERT INTO test VALUES(";
  for(unsigned long long i = 0; i < num_columns; ++i) {
    query_str += "?, ";
  }
  query_str.resize(query_str.size()-2);
  query_str += ")";

  rc = sqlite3_prepare_v2(sqldb
                         ,query_str.c_str()
                         ,-1
                         ,&statement 
                         ,NULL);

  if(rc != SQLITE_OK) {
    // ought to throw something more specific
    throw std::exception("Could not prepare insert statement");
  }

  return statement;
}

// call site
int main() {
  sqlite db;
  try {
    sqlite3_stmt *stmt = create_insert_statement(db, 5);
  }
  catch (...) {
    // and this should catch the specific exception types thrown
    std::cout << "Failed to prepare statement" << std::endl;
  }
}

InAndOutBrennan
Dec 11, 2008

nielsm posted:

...awesome...

Well, that did the trick! Thanks! Sorry for not posting all of it but I figured I got the important bits in there.

As soon as I think I get those loving pointers down...

nielsm
Jun 1, 2009



woptsufp posted:

Well, that did the trick! Thanks! Sorry for not posting all of it but I figured I got the important bits in there.

Lesson learned: It can be really hard to know which parts of your code matter, so always provide it verbatim.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I wanted to get pedantic about returning string literals, like in a case like this:

code:
const char* GetErrorString(int error_code)
{
	switch (error)
	{
		case SOME_ENUMERATED_CODE:
			return "SOME_ENUMERATED_CODE";
		case SOME_OTHER_ENUMERATED_CODE:
			return "SOME_OTHER_ENUMERATED_CODE";

.... many, many, more cases ...

}
This isn't really legal in the most pedantic sense, right? This might work on some platforms but not others; it depends on how the compiler ends up storing those literals. From what I understand the best I can hope for is to have them pass in a char* as another argument that I sully up, hoping not to blow over the end of it. Did I miss anything in this?

Volte
Oct 4, 2004

woosh woosh
String literals are guaranteed to have static storage duration, so it's perfectly safe.

Mr.Radar
Nov 5, 2005

You guys aren't going to believe this, but that guy is our games teacher.
Even if it's not legal in the "strictly following the standards" sense, it should always work. If the data is not stored in a global static region somewhere that's mapped into your process (and therefore visible to all code in your process), where else is going to come from that would break when you return the pointer to it from the function? The one case I can think of is if the data is in a shared object that gets unloaded from your process, but that's an exceptionally rare case.

Mr.Radar fucked around with this message at 16:41 on Dec 31, 2012

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
I can't even think of any remotely sane way to store string literals where returning pointers to them wouldn't work. It'd require either copying them to a new location each time they're used, or mapping parts of the executable in and out of the process's address space, both of which would be insane.

shrughes
Oct 11, 2008

(call/cc call/cc)
As Volte mentioned, it will work, they have static storage duration.

Just don't try to do that in an inline function and then expect the pointers to compare equally.

That Turkey Story
Mar 30, 2003

shrughes posted:

Just don't try to do that in an inline function and then expect the pointers to compare equally.

What makes you say that? I'm pretty sure the pointers are required to compare equal in any case.

pseudorandom name
May 6, 2007

Because you'll end up with multiple copies of the string in different compilation units, which may not be merged by the linker.

That Turkey Story
Mar 30, 2003

pseudorandom name posted:

Because you'll end up with multiple copies of the string in different compilation units, which may not be merged by the linker.

I know that that's what's implied by his post, what I'm saying is that I don't think that the claim is correct, and after briefly skimming through the standard I don't see anything that points to it being true. As far as I'm aware, the behavior should be the same regardless of function inlining, much like how any [non-const] function-static variable is the same between translation units even when the function is inline. Whether the function is inline or not shouldn't have any effect.

e: To be clear, I agree that it is reasonable to expect the pointers to not compare equal, I'm just not convinced it is standard for an implementation to do so.

That Turkey Story fucked around with this message at 09:53 on Dec 31, 2012

UraniumAnchor
May 21, 2006

Not a walrus.

That Turkey Story posted:

e: To be clear, I agree that it is reasonable to expect the pointers to not compare equal, I'm just not convinced it is standard for an implementation to do so.

One copy lives in a shared library, one in the executable?

Only thing that springs to mind.

That Turkey Story
Mar 30, 2003

UraniumAnchor posted:

One copy lives in a shared library, one in the executable?

Only thing that springs to mind.

The standard doesn't deal with "shared libraries."

Hughlander
May 11, 2005

Plorkyeran posted:

I can't even think of any remotely sane way to store string literals where returning pointers to them wouldn't work. It'd require either copying them to a new location each time they're used, or mapping parts of the executable in and out of the process's address space, both of which would be insane.

In Windows, call FreeLibrary() and boom, part of the executable is out of the process's address space. A game I used to work on was an engine as the executable and then a client dll and a server dll. Between levels we'd call FreeLibrary() on the server dll to reclaim memory. :wtc:

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

That Turkey Story posted:

I know that that's what's implied by his post, what I'm saying is that I don't think that the claim is correct, and after briefly skimming through the standard I don't see anything that points to it being true. As far as I'm aware, the behavior should be the same regardless of function inlining, much like how any [non-const] function-static variable is the same between translation units even when the function is inline. Whether the function is inline or not shouldn't have any effect.

e: To be clear, I agree that it is reasonable to expect the pointers to not compare equal, I'm just not convinced it is standard for an implementation to do so.

Both C and C++ require the arrays backing string literals to have static storage duration, but they explicitly decline to make guarantees about whether these arrays are distinct objects from each other:

C11 6.4.5p7 posted:

It is unspecified whether these arrays are distinct provided their elements have the appropriate values.

"C++11 [lex.string posted:

p12"]
Whether all string literals are distinct (that is, are stored in nonoverlapping objects) is implementation-defined.

I would argue that this does weaken the requirements enough to permit a single string literal to yield distinct objects on different executions. Someone with an axe to grind could raise hell with one committee or the other, though, and they'd probably win a concession for non-inline functions (for each of the committees' highly divergent definitions of inline), but there's zero chance they'd win a broad new language guarantee: implementors would fight it tooth-and-nail.

rjmccall fucked around with this message at 01:46 on Jan 1, 2013

That Turkey Story
Mar 30, 2003

rjmccall posted:

I would argue that this does weaken the requirements enough to permit a single string literal to yield distinct objects on different executions.
I interpret it as just stating that multiple strings with overlapping data may potentially refer to the same object (as is described in the note). I.E. if a function has a line char const* a = "hello", * b = "hello"; then it is allowed for an implementation to have a be equal to b. I'd think that if it were meant to be interpreted in the broader sense then it would be opening the door for potential ODR violations, wouldn't it? All a function would have to do is refer to the address of the string or one of its elements (such as store the address of the first element in a char const*, which is clearly very common). Then again, there is no explicit mention of string literals in [basic.def.odr] and they technically don't fall under the types of objects that are touched on (they aren't temporaries, but they also aren't named), so perhaps it would be allowable.

rjmccall posted:

Someone with an axe to grind could raise hell with one committee or the other, though, and they'd probably win a concession for non-inline functions
Right, as a pedant I'd say that if it's interpreted in this broader sense then you technically can't rely on the consistency of the pointer value in non-inline functions. Really though I just don't think that was the original intent of the statement. I also have no idea what the common implementations do here as I've never tested it, but I'd be interested in seeing results in practice.

e: This also shouldn't be a difficult thing to implement, unless I'm missing something. It can be done in the same way as function-static variables -- just treat a given string literal as though it had some implementation-defined name based on an index into the set of string literals of that particular function.

That Turkey Story fucked around with this message at 10:45 on Jan 1, 2013

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
This is where I come in and say the only reason I was seeing problems was that the printf I was trying to use for my returned string literal printed only one thing, but I had given it two things to print. So it wasn't even an issue of the string literals.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

That Turkey Story posted:

I interpret it as just stating that multiple strings with overlapping data may potentially refer to the same object (as is described in the note). I.E. if a function has a line char const* a = "hello", * b = "hello"; then it is allowed for an implementation to have a be equal to b. I'd think that if it were meant to be interpreted in the broader sense then it would be opening the door for potential ODR violations, wouldn't it? All a function would have to do is refer to the address of the string or one of its elements (such store the address of the first element in a char const*, which is clearly very common). Then again, there is no explicit mention string literals in [basic.def.odr] and they technically don't fall under the types of objects that are touched on (they aren't temporaries, but they also aren't named), so perhaps it would be allowable.

Right, as a pedant I'd say that if it's interpreted in this broader sense then you technically can't rely on the consistency of the pointer value in non-inline functions. Really though I just don't think that was the original intent of the statement.

Oh, if we're discussing original intent then yes, absolutely, I think they were just trying to allow strings to be coalesced; I don't think they intended to allow different evaluations of the same expression to yield different objects. But there's no way to give this consistent semantics in either language without completely prohibitive costs. In C++, you'd have to create a symbol with weak linkage for every string used in an inline function, just in case its address turns out to matter — and unlike the symbol for the inline function itself, that's generally not optimizable, because inlining usually won't eliminate the need for the string or tell you that its address is irrelevant. It'd actually be worse than that in C: you'd have to either ban string literals outright in inline functions, or you'd have to make a symbol with external linkage for literally every string appearing in a function with external linkage (i.e. most functions), because you don't know when processing a function definition whether or not there might be an inline definition in a different translation unit. Both are totally prohibitive since basically nobody uses string literals in this way.

That Turkey Story posted:

I also have no idea what the common implementations do here as I've never tested it, but I'd be interested in seeing results in practice.

Well, the obvious emission pattern for a string literal is just to generate an anonymous, internal-linkage global array, preferably in some sort of string-literals data section that the linker will unique. That gives you consistent semantics for non-inline functions, ignoring optimization. Inlining could be a problem if you have an AST inliner (†) — except that as far as I know, every professionally-written C/C++ compiler does its own uniquing of strings within a translation unit, so that's still not a problem. So it's really just the cross-translation-unit situations, and if you need those to have consistent semantics, the compiler needs to start with the global symbols.

† An AST inliner works as if the AST of the called function were copied into the caller, usually either by literally replacing the call expression with a copy of the callee's body, or by processing the callee's body as if processing statements in the caller. AST inliners have to be careful about things like static local variables which need to be unique despite the inlining. The alternative is to have first lowered the callee's AST to some sort of IR (in which a string literal would just be a reference to a global array) and then copy that IR into the IR for the caller (merely creating a new reference to the same global array and thus preserving semantics).

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Rocko Bonaparte posted:

This is where I come in and say the only reason I was seeing problems was that the printf I was trying to use for my returned string literal printed only one thing, but I had given it two things to print. So it wasn't even an issue of the string literals.

Are you not rolling with -Wformat? I thought every compiler had an equivalent to this.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

rjmccall posted:

Are you not rolling with -Wformat? I thought every compiler had an equivalent to this.

Apparently not. I went and screwed it up again just to see, and I don't have any warnings in the compiler messages. I'm using Visual Studio 2010.

Well, I have more problems here, now related to heap stuff. I am building a 64-bit Windows console test program where I intend to blow through a lot of heap. However, I seem to blow through the heap waaaay too early, so I'm trying to get a sanity check here.

I have a class that contains 4 arrays of dynamically-allocated floats. These 4 arrays should have 1024 elements in them. I intend to create 16,800 instances of that class in yet another array. I intend to create two sets of these to compare against each other.

Disregarding anything with memory alignment going on, I should be allocating roughly 1024 elements * 4 arrays per element * 4 bytes per float * 16,800 instances * 2 sets of these = 525MB. We can start to talk about the size of the container for these instances but I consider that negligible to the mass of floating-point arrays I'm allocating.

I have 16GB of RAM. I'm not running other crazy shenanigans at the same time. Somehow I die around the allocation of the arrays for container index 3577. What gives? I'd love to be able to check how much real RAM I have free but I don't know what's a real call to get that. All I could see online was stuff that would factor in virtual memory, and that is some huge, useless, unchanging number.

Captain Cappy
Aug 7, 2008

Could you be overflowing your stack by any chance? You can set the memory limits for the heap and the stack somewhere in the project properties, so give that a try if you want.

The_Franz
Aug 8, 2003

Rocko Bonaparte posted:

Apparently not. I went and screwed it up again just to see, and I don't have any warnings in the compiler messages. I'm using Visual Studio 2010.

If you are using a paid version with code analysis, you can use this to validate your string formatting.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

Captain Cappy posted:

Could you be overflowing your stack by any chance? You can set the memory limits for the heap and the stack somewhere in the project properties, so give that a try if you want.
It turned out I thought I was allocating 1024 elements, but I was allocating many, many, more than that. Yeah, I didn't have the RAM for that kind of stuff.

slovach
Oct 6, 2005
Lennie Fuckin' Briscoe
Trying to come up with an elegant solution for this.

I have a SpriteBatch class, it needs to know about your underlying Vertex structure (and index buffer type) so I thought to just use a template.

code:
template <typename T1, typename T2>
class SpriteBatch
{
...
But I thought about what if I don't want to use an index buffer for my rendering? Is there a way to "overload" my functions so if you don't provide T2, it uses another version?

That Turkey Story
Mar 30, 2003

slovach posted:

But I thought about what if I don't want to use an index buffer for my rendering? Is there a way to "overload" my functions so if you don't provide T2, it uses another version?

Have T2 default to some dummy type and branch accordingly -- you can do this directly by writing partial specializations, or you can do it indirectly with std::conditional.

slovach
Oct 6, 2005
Lennie Fuckin' Briscoe
Noice, that did the trick. Thanks. :frogc00l:

Valtis
Sep 21, 2009
I figured it's good idea to learn how to use unit tests so I picked Boost Test since I had Boost installed. However, when I try to compile any unit tests with C++11 support turned on, I get an error complaining that putenv is undefined, while it compiles just fine when I turn the support off. This is a problem because I'd like to add unit tests to my personal project which is written in C++11. Is there any way to make boost test behave nicely? I'm using MinGW 4.7.2.

EDIT: GCC defines __STRICT_ANSI__ when compiling with -std=c++11 or -std=c++0x which disables putenv among other things, so simple #undef __STRICT_ANSI__ fixed this.

Valtis fucked around with this message at 17:10 on Jan 10, 2013

pliable
Sep 26, 2003

this is what u get for "180 x 180 avatars"

this is what u fucking get u bithc
Fun Shoe
It's been a long rear end time since I've written C, and so I need some assistance.

I'd like to read floating point numbers (separated by whitespace) from a text file while dynamically creating a 2D array (the numbers are a matrix, with each row ending with a '\n'). I need to go for performance, so I figure this would be the fastest method of doing so, instead of reading each line into a buffer with fgets, then running through that line with fscanf(). It was suggested to use mmap to map the file into memory first so I'd get faster I/O, but I'm not entirely sure how to use it, especially with what I want to do.

Googling around, I haven't seen very many helpful code examples for my use case. Any C guru's wanna suggest how to start writing this? Thanks!

nielsm
Jun 1, 2009



For a single, linear read of the file I don't think you'll gain anything from mmapping it. The standard buffering provided by OS and stdlib should be sufficient for performance.

I'd suggest just writing the naive implementation first and see how it performs. If it's too slow then measure it and figure out what the actual hot spots are.

seiken
Feb 7, 2005

hah ha ha
Also, writing floating-point values (as text) to a file and reading them back in won't necessarily give you the exact same values. Unless you care about the file being human-readable, you might want to consider writing binary data instead (this is easier and will improve filesize, performance and accuracy).

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!

seiken posted:

Also, writing floating-point values (as text) to a file and reading them back in won't necessarily give you the exact same values. Unless you care about the file being human-readable, you might want to consider writing binary data instead (this is easier and will improve filesize, performance and accuracy).
Though it can make cross-platform-ness trickier.

Progressive JPEG
Feb 19, 2003

roomforthetuna posted:

Though it can make cross-platform-ness trickier.

Binary representation of floating point is an IEEE standard isn't it? Other than maybe endianness.

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!

Progressive JPEG posted:

Binary representation of floating point is an IEEE standard isn't it? Other than maybe endianness.
Yeah, I was thinking endian. Not sure if that's an issue these days, macs are the same way round now right? Also should be aware of possible complications with compiler differences if you're binary-IO-ing structs and not just the primitive types.

Adbot
ADBOT LOVES YOU

FamDav
Mar 29, 2008

seiken posted:

Also, writing floating-point values (as text) to a file and reading them back in won't necessarily give you the exact same values. Unless you care about the file being human-readable, you might want to consider writing binary data instead (this is easier and will improve filesize, performance and accuracy).

Actually, the standard specifically states that every floating point number have a character representation that is also convertible back to the original floating point number. This is 9 decimal digits for a float and 17 for a double.

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