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
b0lt
Apr 29, 2005

KNITS MY FEEDS posted:

zmq::message_t msg(sbuf.data(), sizeof(char *) * sbuf.size(), NULL, NULL);

This is wrong, presumably sbuf.size() gives you the size of the buffer in chars, not char pointers. I don't know if that'd cause the deserialization to fail, but it might.

Adbot
ADBOT LOVES YOU

Acer Pilot
Feb 17, 2007
put the 'the' in therapist

:dukedog:

This was how I solved this:

code:
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, data);
zmq::message_t msg(sbuf.size());
memcpy(msg.data(), sbuf.data(), sbuf.size())
I'm not too sure why I needed to do that though.

Dren
Jan 5, 2001

Pillbug

b0lt posted:

typedef goes the other way, it'd be typedef int silly_t.

I had the typedef syntax on a post it in my cube for years until someone walked in, saw it, and said "You know typedef has the same argument order as cp, right? It's like you copy the type into the new name."

Jersey Mike posted:

I've been recommended several books for learning the C programming language, and the two that show up most are "The C Programming Language" and "C Programming:A Modern Approach". Most of the individuals I ask tell me to go with the former, but others tell me the latter is better. Bearing in mind that I am completely new programming, does anyone happen to know which would be better?

I plan on going to college for computer science next Spring but I really want to get a little knowledge under my belt beforehand. My only experience with any sort of coding is HTML and CSS,some BASIC coding, and I've recently picked up JavaScript. I realize none of those are on the same level of difficulty, but I have a natural ability for problem solving, logic, and picking up new areas of study.
I don't know which ones are good but have you looked into opencourseware? http://www.mycplus.com/featured-articles/best-free-programming-courses-online/

I think you'd probably learn more from a course than from a book. You might want the book too. The MIT course recommends "The C Programming Language".

chglcu
May 17, 2007

I'm so bored with the USA.

Dren posted:

I had the typedef syntax on a post it in my cube for years until someone walked in, saw it, and said "You know typedef has the same argument order as cp, right? It's like you copy the type into the new name."

Personally, I just find it easiest to remember that it's the same as a variable declaration but with typedef in front.

PsychicToaster
Jan 12, 2010

Dren posted:

I had the typedef syntax on a post it in my cube for years until someone walked in, saw it, and said "You know typedef has the same argument order as cp, right? It's like you copy the type into the new name."

I don't know which ones are good but have you looked into opencourseware? http://www.mycplus.com/featured-articles/best-free-programming-courses-online/

I think you'd probably learn more from a course than from a book. You might want the book too. The MIT course recommends "The C Programming Language".

Holy poo poo, that's excellent. Thank you for pointing that out. I appreciate that.

raminasi
Jan 25, 2005

a last drink with no ice
I think the chief objection people have to "The C Programming Language" (colloquially referred to as "K&R") is that it doesn't cover the latest C standard, C99. It's great for the rest of C but you'll want something to cover the newer stuff as well.

UraniumAnchor
May 21, 2006

Not a walrus.

Dren posted:

I had the typedef syntax on a post it in my cube for years until someone walked in, saw it, and said "You know typedef has the same argument order as cp, right? It's like you copy the type into the new name."

typedef oldtype newtype;

Just remember "ton". :shepface:

Volte
Oct 4, 2004

woosh woosh
Typedef is just like a regular variable declaration with the word typedef in front. int variable; -> typedef int typename;

This particularly applies to function pointers.

mobby_6kl
Aug 9, 2009

by Fluffdaddy

GrumpyDoctor posted:

I think the chief objection people have to "The C Programming Language" (colloquially referred to as "K&R") is that it doesn't cover the latest C standard, C99. It's great for the rest of C but you'll want something to cover the newer stuff as well.

As long as it's at least the ANSI C book, I think there shouldn't any issues starting with K&R :)

Cancelbot
Nov 22, 2006

Canceling spam since 1928

Suspicious Dish and Edison was a dick

Brilliant! Thanks. Maybe i'll suck less at C someday.

Rothon
Jan 4, 2012

GrumpyDoctor posted:

I think the chief objection people have to "The C Programming Language" (colloquially referred to as "K&R") is that it doesn't cover the latest C standard, C99. It's great for the rest of C but you'll want something to cover the newer stuff as well.

C11's the latest C standard.

raminasi
Jan 25, 2005

a last drink with no ice

Rothon posted:

C11's the latest C standard.

Well that's embarrassing, but my point is the same.

Paul MaudDib
May 3, 2006

TEAM NVIDIA:
FORUM POLICE
Is there a good (preferably thread-safe) transactional map structure in any library out there?

I found a library called nbds which does what I want, but it's in super rough shape and not actively maintained any more. It wouldn't even build without me fixing the makefile (needed -lpthread moved to the linker stage), which doesn't fill me with confidence, and the transaction support was described as "a toy model".

Atomic has transactional maps, but the transactions are implemented directly in the structure rather than thread-local memory. It looks a little cleaner than nbds, but what's on the site is literally the first release.

SQLite is going to be way overkill for this and (at a guess) would probably be slower than using Atomic with locks.

Paul MaudDib fucked around with this message at 23:39 on Apr 10, 2013

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


This is a hypothetical question since we've already thrown out this code, but I just ran into something in a legacy codebase that looked something like this (not so abstracted, obviously):

C++ code:
void fart(int x, int y)
{
 // ...
}
// ...
int i = 0;
fart(i++, i);
// i == 1
:psyduck:

So what the hell would x and y have been for this call? Is there a standard behavior for this or does it vary by compiler?

b0lt
Apr 29, 2005

Ciaphas posted:

This is a hypothetical question since we've already thrown out this code, but I just ran into something in a legacy codebase that looked something like this (not so abstracted, obviously):

C++ code:
void fart(int x, int y)
{
 // ...
}
// ...
int i = 0;
fart(i++, i);
// i == 1
:psyduck:

So what the hell would x and y have been for this call? Is there a standard behavior for this or does it vary by compiler?

Undefined behavior

Xerophyte
Mar 17, 2008

This space intentionally left blank

Ciaphas posted:

So what the hell would x and y have been for this call? Is there a standard behavior for this or does it vary by compiler?

http://en.cppreference.com/w/cpp/language/eval_order posted:


1) If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.
C++ code:
i = ++i + i++; // undefined behavior
i = i++ + 1; // undefined behavior (but i = ++i + 1; is well-defined)
f(++i, ++i); // undefined behavior
f(i = -1, i = -1); // undefined behavior
2) If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined.
C++ code:
cout << i << i++; // undefined behavior
a[i] = i++; // undefined bevahior
The standard guarantees that the arguments will be placed on the stack from left to right, but compilers can (and, for performance reasons, will) definitely evaluate them in arbitrary order.

Edit: or, y'know, what they said.

Xerophyte fucked around with this message at 11:53 on Apr 11, 2013

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


Thanks folks, good to know the code was exactly as lovely as I thought it was for once (instead of being a nice esoteric trick or something). :v:

raminasi
Jan 25, 2005

a last drink with no ice
Can someone either point me to a resource or just explain the right way to follow the rule of five by using swap idioms? (I barely even know how to describe this poo poo.) I feel like I've almost got it, but I can't figure out how to deal with the fact that it seems like I should be using move assignment to implement swap while using swap to implement move assignment.

FAT32 SHAMER
Aug 16, 2012



Tusen Takk posted:

This is awesome, thanks man!! I'll take another whack at it tomorrow, but it made a whole lot of things snap :)

I managed to get it working perfectly, thanks guys!

C++ code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct //structure&type definition//
	{ 
		int ranking; //city's ranking//
		char city_name[20]; //city's name//
		char state[2];	//city's state in 2-char code//
		int population; //city's population size//
		float percent_change; //city's percent of change//
	}city_t; //name of the structure//

void read_file(city_t *database) //beginning of file-reading function//
{
	//read in the file until we hit End of File//
	int i=0;
	int ranking; //city's ranking//
	char city_name[20]; //city's name//
	char state[2];	//city's state in 2-char code//
	int population; //city's population size//
	float percent_change; //city's percent of change//

	//create file handler and open the file for reading//
	FILE *infile;
	infile = fopen("cities.dat","r");

	//if we cannot open the file, print an error message and quit//
	if(infile == NULL)
	{
		printf("Cannot open cities.dat for input. Please check file location");
	}

	else
	{		
		while(fscanf(infile, "%d %s %s %d %f", &ranking, city_name, state, &population, &percent_change)!=EOF)
		{			
			database[i].ranking = ranking;
			strcpy(database[i].city_name, city_name);
			strcpy(database[i].state, state);
			database[i].population = population;
			database[i].percent_change = percent_change;

			i++;			
		}

	}
	fclose(infile); //closes the file cities.dat//
	
}

void print_database(city_t *database) //prints the information read from the file on the screen//
{
	
	int i=0;

	printf("Rank\t City Name\t State\t Population\t Percent Change\n");
	for(i = 0; i < 10; i++)
	{
		printf("%d\t %s\t %s\t %d\t\t %0.1f\n", database[i].ranking, database[i].city_name, database[i].state, database[i].population, database[i].percent_change);
		//lists the rank, city name, state, population, and percent change in a nice box//
	}
}


int main(void)
{
	//create the database//
	city_t database[10];

	//read in the file's contents
	read_file(database);

	//print out the contents//
	print_database(database);

	return 0;
}	

That Turkey Story
Mar 30, 2003

GrumpyDoctor posted:

Can someone either point me to a resource or just explain the right way to follow the rule of five by using swap idioms? (I barely even know how to describe this poo poo.) I feel like I've almost got it, but I can't figure out how to deal with the fact that it seems like I should be using move assignment to implement swap while using swap to implement move assignment.

A "rule of 5" isn't really a thing in the way the "rule of 3" is. While having one of copy, copy-assign, or destructor generally means that you should have all 3, the same cannot be said with the addition of move and move-assign. Simply having a copy or a copy-assign or a destructor rarely has any implication at all as to whether or not you should make separate move operations (and having a move constructor generally doesn't even imply that you need a move-assign operator, etc.). The benefits of move operations come primarily from optimization over corresponding copy operations, their simplicity of implementation over their copy counter-parts (proper copy semantics can sometimes be unclear or difficult to implement so it's not worth implementing copy/copy-assign if all you really need in practice is movability), and their ability to almost always easily be noexcept. I'm sure there are more benefits I left out but those are probably the most common.

Anyway, swap idioms are more of a C++98 thing than a C++11 thing. They basically exist because C++98 didn't have move semantics. Now that we have move semantics, using swap for implementing things like copy-assign is now done via move-assign instead, in a similar manner. Also keep in mind that the default std::swap implementation uses move operations, so overloading swap often isn't that important if your type is movable.

raminasi
Jan 25, 2005

a last drink with no ice

That Turkey Story posted:

A "rule of 5" isn't really a thing in the way the "rule of 3" is. While having one of copy, copy-assign, or destructor generally means that you should have all 3, the same cannot be said with the addition of move and move-assign. Simply having a copy or a copy-assign or a destructor rarely has any implication at all as to whether or not you should make separate move operations (and having a move constructor generally doesn't even imply that you need a move-assign operator, etc.). The benefits of move operations come primarily from optimization over corresponding copy operations, their simplicity of implementation over their copy counter-parts (proper copy semantics can sometimes be unclear or difficult to implement so it's not worth implementing copy/copy-assign if all you really need in practice is movability), and their ability to almost always easily be noexcept. I'm sure there are more benefits I left out but those are probably the most common.

Anyway, swap idioms are more of a C++98 thing than a C++11 thing. They basically exist because C++98 didn't have move semantics. Now that we have move semantics, using swap for implementing things like copy-assign is now done via move-assign instead, in a similar manner. Also keep in mind that the default std::swap implementation uses move operations, so overloading swap often isn't that important if your type is movable.

Thanks for your answer, although its main purpose was to show me that I asked my question wrong. What I really should have just said was where do I go to learn best practices for writing copy and move constructors and assignment operators because I feel like I've seen three or four different ways to do it and I trust this thread more than I do wandering around stackoverflow and random blog posts in what feels like a drunken haze.

nielsm
Jun 1, 2009



Tusen Takk posted:

I managed to get it working perfectly, thanks guys!

A purely stylistic thing, you're using a strange comment style that could look like a confusion of traditional C style block comments and C++ style line comments.

In traditional C, you open a comment block with /* and it then runs until a following */ which might even be on a different line.
In C++ you can also use line comments which are opened by // and then run until the end of the line. C99 adopted that style too, so now both are legal in each language.

But there doesn't seem to be any point to you using line comments and then putting a // sequence at the end of them, it does nothing.

FAT32 SHAMER
Aug 16, 2012



nielsm posted:

A purely stylistic thing, you're using a strange comment style that could look like a confusion of traditional C style block comments and C++ style line comments.

In traditional C, you open a comment block with /* and it then runs until a following */ which might even be on a different line.
In C++ you can also use line comments which are opened by // and then run until the end of the line. C99 adopted that style too, so now both are legal in each language.

But there doesn't seem to be any point to you using line comments and then putting a // sequence at the end of them, it does nothing.

Ah, yeah I guess it is a cross between the two :v:. I think that that's how you make comments in whatever "language" that Rainmeter uses, too, since it seemed really natural to use the //words// thing I'm doing there...

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Xerophyte posted:

The standard guarantees that the arguments will be placed on the stack from left to right

I'm curious what you think this means.

To be less of an rear end: on pretty much every platform, it is true that, when arguments are passed on the stack, later arguments are passed at higher stack addresses. But this means nothing about anything actually visible to the source language, like the address of the formal parameter variable in the callee. And many platforms do pass some or even many arguments in registers, and it's frequently possible to have one argument on the stack, the next in a register, and then the next back on the stack.

rjmccall fucked around with this message at 01:21 on Apr 11, 2013

That Turkey Story
Mar 30, 2003

GrumpyDoctor posted:

Thanks for your answer, although its main purpose was to show me that I asked my question wrong. What I really should have just said was where do I go to learn best practices for writing copy and move constructors and assignment operators because I feel like I've seen three or four different ways to do it and I trust this thread more than I do wandering around stackoverflow and random blog posts in what feels like a drunken haze.

There's not really an authoritative source or a simple "always do this" kind of answer, so you pretty much just have to go based on what makes sense for your particular situation. If you want all 4 operations (copy, move, copy-assign, move-assign) and have the ability to provide move and move-assign operations that are more efficient and/or have more strict guarantees than than their "copy" counterparts, in most cases it's probably "best" to implement move, copy, and move-assign on their own, then implement copy-assign simply in terms of copy and move-assign. This gives you a copy-assign that will be correct and that likely has the most strict exception guarantee possible for the type. The act of creating the move and move-assign operations also implicitly improves the efficiency/guarantees of std::swap.

If you've done all of that, manually writing a copy-assign operation without using copy and move-assign, or explicitly implementing a swap operation will most likely not be able to provide any stricter guarantees and would likely not be able to decrease complexity by anything but a constant factor (and depending on the type and your compiler's optimizations there may not be any difference at all). In other words, the only reason to do either of those things would be after profiling.

The only other thing I guess I'll stress again is don't use the swap idiom for new types in C++11. Use move semantics directly instead.

OddObserver
Apr 3, 2009
Oh, std::swap is now written in terms of std::move, isn't it?

That Turkey Story
Mar 30, 2003

OddObserver posted:

Oh, std::swap is now written in terms of std::move, isn't it?

Yes. It moves operand "A" to a temporary, then move-assigns from operand "B" to operand "A", and finally move-assigns from the temporary to operand "B."

MrMoo
Sep 14, 2000

Is there a simple reason C++14 has the :=: swap operator?

That Turkey Story
Mar 30, 2003

MrMoo posted:

Is there a simple reason C++14 has the :=: swap operator?

It's just been proposed. The rationale makes reference to the copy-swap idiom (though as mentioned earlier, that's unnecessary in modern C++) and to the difficulty in properly calling swap in a generic context. I'm not convinced a new operator is necessary or that it will make it into the next standard.

Xerophyte
Mar 17, 2008

This space intentionally left blank

rjmccall posted:

I'm curious what you think this means.

To be less of an rear end: on pretty much every platform, it is true that, when arguments are passed on the stack, later arguments are passed at higher stack addresses. But this means nothing about anything actually visible to the source language, like the address of the formal parameter variable in the callee. And many platforms do pass some or even many arguments in registers, and it's frequently possible to have one argument on the stack, the next in a register, and then the next back on the stack.

Since you ask, what I thought it meant was that the standard calling conventions guaranteed that the caller always placed the evaluated arguments on the stack in ascending order without making any guarantees on how those arguments would be evaluated. On bothering to check I realize that isn't the case for cdecl and stdcall even, never mind other conventions and platforms. Thanks for pointing it out, I'd have happily lived on in ignorance otherwise.

evensevenone
May 12, 2001
Glass is a solid.
This is kind of dumb, but what's a good, endianness agnostic way to mask out the least significant bits of an integer? Kind of like a reverse modulo--it should have the result of x - (x%(0xFF)) (where 0xFF depends on how many bits you want to dump)
I've been doing this:
C code:
uint16_t foo = 0xDEAD
foo = (foo >> 8) << 8;
Is there a better way? It looks like poo poo, and I'm not 100% sure about the semantics, also, you can't do more complicated maskings. My inclination would be to
C code:
foo = foo & 0xFF00
But I suspect this would depend on the endianness of the architecture. The other option is using modulo, but modulo is actually really slow on certain processors.

evensevenone fucked around with this message at 15:23 on Apr 11, 2013

Vanadium
Jan 8, 2005

foo &= 0xff00 should work regardless of endianness. It's not like you have to write integer literals backwards on some architectures.

That Turkey Story
Mar 30, 2003

Vanadium posted:

foo &= 0xff00 should work regardless of endianness. It's not like you have to write integer literals backwards on some architectures.

Right. Remember that 0xFF00 is not some endian-unaware bit pattern even though you may often think about it as one. In C and C++ (and many other languages) it is a just number in hex and is the same as writing the decimal literal 65280. You only really need to worry about endian-ness when you are doing things like saving/loading binary data from files that need to be able to be opened on computers of a different endian-ness, or similarly when sending/receiving data across a network.

evensevenone
May 12, 2001
Glass is a solid.
Yeah, actually that makes perfect sense.

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


I've got code that looks a little like this, part of a class that I'm trying to port from Solaris SunCC 12.1 to Linux gcc 4.6:

C++ code:
// hpp
class ICString {
  // ...
  typedef boost::unordered_map<std::string, const std::string*> StringMap;
  static StringMap mStrings;
  // ...
};

// cpp
#include "ICString.hpp"

StringMap ICString::mStrings;
// ...
On Solaris this works fine, but on linux the program fails immediately with a floating point exception. Near as I can tell from gdb (no GUI installed yet on this box and I'm terrible at command line debugging), the exception is being thrown in static initialization. Some stuff about boost::hash in there too, but unfortunately I can't copy the stack trace to this machine so I can post it (different networks, and my work machine is off the internet :().

Anyway, is there something wrong with using strings as a key in an unordered map or something? My only hint is the mention of boost::hash in the exception stack.

Ciaphas fucked around with this message at 22:06 on Apr 11, 2013

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


Follow-up post because I've got a guess at the problem I want to run. I found other code that looks like this:

C++ code:
//LuaScript.hpp
#include "ICString.hpp"

class LuaScript {
  // ...
  struct FuncMap {
    ICString name;
    ICString mapName;
    // ...
  };

  static FuncMap mFuncMap;
  // ...
};

//LuaScript.cpp
#include LuaScript.hpp

LuaScript::FuncMap LuaScript::mFuncMap;
I wondered if maybe the static initializer for LuaScript::mFuncMap was running before the one for ICString::mStrings. ICString does have a default constructor that checks mStrings for "" keys, so if mStrings isn't initialized yet, that would break pretty hard. Does this make sense? Is it possible for this to happen, where one static initializer could depend on another but they fire in the wrong order? If so, what can I actually do about it?

(edit) Checked google after posting this and this does, indeed, seem to be the faux pas I thought it was. Well, damnit. Follow-on question applies: what can I do about this without having to refactor a LOT of code to make one of these things non-static?

Ciaphas fucked around with this message at 22:06 on Apr 11, 2013

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Put them in the same file, play games with link order, or use the init_priority attribute.

nielsm
Jun 1, 2009



You can use just-in-time initialisation. Instead of having a class static variable, make a static (or global) function in the class that returns a reference to an instance of the class, and have it return a static variable inside that function.
It's not the neatest solution, but it should work.

code:
// at global scope
LuaScript::FuncMap & GetLuaScriptFuncMap()
{
    static LuaScript::FuncMap the_map(constructor, arguments);
    return the_map;
}

rufius
Feb 27, 2011

Clear alcohols are for rich women on diets.

Ciaphas posted:

Follow-up post because I've got a guess at the problem I want to run. I found other code that looks like this:

...

I wondered if maybe the static initializer for LuaScript::mFuncMap was running before the one for ICString::mStrings. ICString does have a default constructor that checks mStrings for "" keys, so if mStrings isn't initialized yet, that would break pretty hard. Does this make sense? Is it possible for this to happen, where one static initializer could depend on another but they fire in the wrong order? If so, what can I actually do about it?

(edit) Checked google after posting this and this does, indeed, seem to be the faux pas I thought it was. Well, damnit. Follow-on question applies: what can I do about this without having to refactor a LOT of code to make one of these things non-static?

I think you can generally expect consistent behavior but there's no guarantee on initialization order. I'm almost certain that isn't in the spec but I do not have it memorized so I could be wrong. What nielsm mentioned above is what I would likely do.

Adbot
ADBOT LOVES YOU

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


nielsm posted:

You can use just-in-time initialisation. Instead of having a class static variable, make a static (or global) function in the class that returns a reference to an instance of the class, and have it return a static variable inside that function.
It's not the neatest solution, but it should work.

code:
// at global scope
LuaScript::FuncMap & GetLuaScriptFuncMap()
{
    static LuaScript::FuncMap the_map(constructor, arguments);
    return the_map;
}

Thanks all, this is more or less what I ended up doing. Worked a treat.

Got another related problem that I'll address with a short question: is there any problem with doing I/O in a constructor for an object that's being statically initialized? In this specific case the code is using ifstream to open a file and initialize some other stuff, but I'm finding that said other stuff goes uninitialized.

(edit) Actually, turns out the problem is different than I thought it was, but still similar to my static initialization problem.

C++ code:
// Filenames.hpp
namespace Filenames {
   const std::string F1 = "foo.txt";
   // ...
};

// Bar.hpp
#include "Filenames.hpp"

class Bar
{
public
   Bar () {ifstream f(Filenames::F1, ...);}
};

// Foo.hpp
#include "Bar.hpp"

class Foo
{
   static Bar mB;
};
Is there a chance Filenames::F1 won't be initialized in time for Foo::mB to be statically constructed? Or do namespace values work differently?

Ciaphas fucked around with this message at 20:13 on Apr 12, 2013

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