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
Mr.Radar
Nov 5, 2005

You guys aren't going to believe this, but that guy is our games teacher.

ultra-inquisitor posted:

Virtual functions are designed to avoid horrors such as switch-on-type.
Yeah, if you're using the command pattern as described by Wikipedia I'm having a hard time imagining why virtual function(s) wouldn't be enough to do what you want. Look at the example of the command pattern in C++ in that Wikipedia article.

Adbot
ADBOT LOVES YOU

HFX
Nov 29, 2004

ultra-inquisitor posted:

Virtual functions are designed to avoid horrors such as switch-on-type.

It can be an issue if you have possibly multiple types of objects which don't share hierarchy or you need to make a special call thus the virtual won't match for all possibilities.

This is most likely to occur in either input or interacting with OPC (Other Peoples Code). Examples would be libraries, certain rpcs, etc.

Usually though, the above about victuals is correct.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Hmm as Wikipedia shows it wasn't how it was originally represented to me, so I can only fault myself for bringing it up. Design wise I was trying to come up with something that would cause different things to happen based on a protocol from a stream. I wanted to do it in a way that there wasn't such a tight coupling between what was parsing the stream and what responded to it. So I thought I'd just pass a base class between them. Both ends would still need some awareness of what was really being passed, so I added a tag in the base class to help figure it out.

I don't know what to think about the tag because without another level of inheritance, it could turn stupid. Say, there is little value in an object being purely base class A, so we strike that out. B inherits A, and we have a case for that. Say then C inherits B. Then it would be tagged as C, but code that works on B could have a say in what happens. So it's basically taking over inheritance in a kind of lovely way.

That Turkey Story brought up trying to code C++ like Java, so here is a case where in Java one could just sprinkle instanceof around to some extent. That could tell if an object coming in as type A was really C, but also if it could be B. With my one-level tag, call I could tell is if it's A, B, or C.

Mr.Radar
Nov 5, 2005

You guys aren't going to believe this, but that guy is our games teacher.
You could do double-dispatch: example.

Foiltha
Jun 12, 2008
I'm really new to templates (and C++ really) and am having some problems. How do you define a function in a template class that takes an instance of another template class as an argument? I'm basically trying to create a 4-dimensional vector class to use with homogeneous coordinates, so I'd really like it to have constructor that takes a 3-dimensional vector and sets the 4th component to 1 as default. So let's say I have something like this:

code:
template <class T> class Vector3 {

    public:
    
    T _x, _y, _z;

    Vector3(T x, T y, T z): _x(x), _y(y), _z(z) {
    }

    //Overloaded operators, accessors dot products etc here
    ...

};

template <class T> class Vector4 {
 
     public:

     T _x, _y, _z, _w;

     Vector4(T x, T y, T z, T w = 1): _x(x), _y(y), _z(z), _w(w) {
     }

     //Overloaded operators, accessors, etc here
     ....

};

How do I define a constructor in Vector4 that accepts an instance of class Vector3? I tried defining it like this in the header:

code:
    template <class T2> Vector4(const Vector3<T2> &vec) {
	_x = vec.x();
	_y = vec.y();
	_z = vec.z();
	_w = 1;
    }
Which doesn't compile but if declare Vector3 to be a friend of Vector4 in the Vector4 header like this:
code:
template <class T2> friend class Vector3;
Now it works as it should. Is this the right way to do something like this? As I said, I really haven't used templates much before.

Foiltha fucked around with this message at 13:33 on Jul 3, 2010

Mr.Radar
Nov 5, 2005

You guys aren't going to believe this, but that guy is our games teacher.
Hmm, what error message are you getting? I tried your example code and it works for me.

Jonnty
Aug 2, 2007

The enemy has become a flaming star!

I'm getting some weird behaviour in the file-reading code of some C I'm writing. It's supposed to read every 4 bytes from a file and put them into an array (arrays[0]) of unsigned ints. This appears to work file for a 56KB file (though the program runs slightly incorrectly which might be as a result of this or, more likely, something in the rest of the program) however if I run it for something more like 3MB it seems to segfault having read about 128KB.

Even weirder (or perhaps I don't understand gdb enough) the gdb backtrace seems to 'skip out' which part of the reading function (parse_and_load) is causing the problem. Here's the full output, including stuff printed by the code:

code:
(gdb) run codex.umz 
Starting program: /mnt/home/jadh/Python/icfp06/um codex.umz
parse
1000
2000
4000
8000
16000
32000
64000

Program received signal SIGSEGV, Segmentation fault.
__memcpy_ssse3 () at ../sysdeps/i386/i686/multiarch/memcpy-ssse3.S:332
332     ../sysdeps/i386/i686/multiarch/memcpy-ssse3.S: No such file or directory.
        in ../sysdeps/i386/i686/multiarch/memcpy-ssse3.S
(gdb) bt
#0  __memcpy_ssse3 () at ../sysdeps/i386/i686/multiarch/memcpy-ssse3.S:332
#1  0x00283ff4 in ?? () from /lib/tls/i686/cmov/libc.so.6
#2  0x08048e7b in main (argc=2, argv=0xbffff384) at um.c:321
and here's the section of code in question:

code:

unsigned int swap4(unsigned int dw) {
  /* Swap the bytes around for correct endianness */
  unsigned int tmp;
  tmp =  (dw & 0x000000FF);
  tmp = ((dw & 0x0000FF00) >> 0x08) | (tmp << 0x08);
  tmp = ((dw & 0x00FF0000) >> 0x10) | (tmp << 0x08);
  tmp = ((dw & 0xFF000000) >> 0x18) | (tmp << 0x08);
  return tmp;
}

void parse_and_load(char *progfile) {
  /*
  Parse the program file into 32-bit ints
  the load it into the 0-array
  */
  int i;
  printf("parse\n");
  unsigned int *temp = NULL;
  unsigned int *file = NULL;
  unsigned int bufsize = 0;
  unsigned int filesize = 0;
  FILE *fp;
  
  if (!(fp = fopen(progfile, "r"))) {
    printf("couldn't open program file\n");
    abort();
  }
  
  bufsize = 500;
  //progressively load the file into a buffer,
  //doubling its size each iteration
  while((!ferror(fp)) && (!feof(fp))) {
    bufsize *= 2;
    temp = file;
    file = malloc(bufsize * sizeof(int));
    if (temp) { //avoid first iter
      memcpy(file, temp, bufsize * sizeof(int));
      free(temp);
    }
    filesize += fread(file+filesize, 4, bufsize-filesize, fp);
    printf("%u\n", filesize);
  }
    
  if (ferror(fp)) {
    printf("error reading program file!\n");
    abort();
  }
  fclose(fp);
  
  arrays[0] = malloc((filesize+1) * sizeof(int));
  memcpy(arrays[0]+1, file, filesize * sizeof(int));
  arrays[0][0] = filesize; //store array length
  free(file);
  printf("read\n");
  //swap every bit for correct endianness
  for (i=1; i<=filesize; i++) {
    arrays[0][i] = swap4(arrays[0][i]);
  }
  
  printf("end parse\n");
}



int main(int argc, const char* argv[]) {
  if (argc < 2) {
    printf("Usage: um <program file>");
    abort();
  }
  parse_and_load(argv[1]);
  run_cycle();
  return 0;
}
I'm new to gdb and doing this sort of stuff with C, so apologies if I'm doing something blatantly wrong and sorry that the code's a bit long.

OddObserver
Apr 3, 2009
I suggest you learn to use valgrind...

Jonnty
Aug 2, 2007

The enemy has become a flaming star!

OddObserver posted:

I suggest you learn to use valgrind...

Ah, I'd heard about how good valgrind is but completely forgotten. Thanks, you've not only helped me solve the main problem I was having, but (I think) the one I mentioned in passing, too.

ctz
Feb 6, 2003
code:
  while((!ferror(fp)) && (!feof(fp))) {
    bufsize *= 2;
    temp = file;
    file = malloc(bufsize * sizeof(int));
    if (temp) { //avoid first iter
->    memcpy(file, temp, bufsize * sizeof(int));
      free(temp);
    }
  ...
1. Use realloc, this is what it is designed for.
2. On the second run through the loop, 'temp' points to bufsize / 2 words, but you copy bufsize words from it. It probably fails at the point it does, because it's only then that you run off pages owned by your process. But even before then, it's grossly undefined.
3. On the second run through the loop, you copy data into a possibly NULL pointer (file, returned from malloc).

ctz fucked around with this message at 15:34 on Jul 4, 2010

Jonnty
Aug 2, 2007

The enemy has become a flaming star!

ctz posted:

code:
  while((!ferror(fp)) && (!feof(fp))) {
    bufsize *= 2;
    temp = file;
    file = malloc(bufsize * sizeof(int));
    if (temp) { //avoid first iter
->    memcpy(file, temp, bufsize * sizeof(int));
      free(temp);
    }
  ...
1. Use realloc, this is what it is designed for.
2. On the second run through the loop, 'temp' points to bufsize / 2 words, but you copy bufsize words from it. It probably fails at the point it does, because it's only then that you run off pages owned by your process. But even before then, it's grossly undefined.
3. On the second run through the loop, you copy data into a possibly NULL pointer (file, returned from malloc).

1. Yeah I discovered this function last night. Awesome.
2. Yeah, valgrind pointed this out for me, but thanks.
3. welp, thanks

haximus prime
Nov 23, 2007
buttes
Hey guys, I've got a quick question about strings in C.

I'm trying to make a function that based on the input, returns a string of text. printf();'s wouldn't work because I'm using the function to give me strings for stuff like button names and general text around the program, things that wouldn't always have the same position.

I've looked around online about how C handles strings, and it looks like it uses arrays. It seems really inefficient to make a bunch of different arrays for 4 or 5 letter strings.

I am using ncurses pretty heavily in this program, so maybe something can be done involving that but from what I know I'm drawing a blank.

Thanks guys, this is a really useful thread. :)

covener
Jan 10, 2004

You know, for kids!

haximus prime posted:

Hey guys, I've got a quick question about strings in C.

I'm trying to make a function that based on the input, returns a string of text. printf();'s wouldn't work because I'm using the function to give me strings for stuff like button names and general text around the program, things that wouldn't always have the same position.

snprintf if you need to return a formatted string

quote:

I've looked around online about how C handles strings, and it looks like it uses arrays. It seems really inefficient to make a bunch of different arrays for 4 or 5 letter strings.

Probably no inefficiency to worry about. You can store them as literals in your program if there are just a few, and decide if you need to strdup what you return or not.

Paniolo
Oct 9, 2007

Heads will roll.

haximus prime posted:

I've looked around online about how C handles strings, and it looks like it uses arrays. It seems really inefficient to make a bunch of different arrays for 4 or 5 letter strings.

You must be coming from another language where arrays are objects with overhead.

A 5 character array in C takes exactly 5 bytes of memory.

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

Also, don't forget that if you're just returning string literals, you can just return a pointer to that literal as much as you want, with no memory overhead beyond the initial declaration.

Also also, come on, son:

Paniolo posted:

A 5 character string in C takes exactly 6 bytes of memory.

Dijkstracula fucked around with this message at 04:06 on Jul 5, 2010

shrughes
Oct 11, 2008

(call/cc call/cc)

haximus prime posted:

I've looked around online about how C handles strings, and it looks like it uses arrays. It seems really inefficient to make a bunch of different arrays for 4 or 5 letter strings.

I'm curious about how you would recommend handling strings.

The1ManMoshPit
Apr 17, 2005

Pack 4-character strings into a single 32-bit integer for great justice.

Don't actually do this.

Null Pointer
May 20, 2004

Oh no!

Paniolo posted:

You must be coming from another language where arrays are objects with overhead.

A 5 character array in C takes exactly 5 bytes of memory.

Mistakes like this are why newer languages have arrays as objects with overhead.

litghost
May 26, 2004
Builder

The1ManMoshPit posted:

Pack 4-character strings into a single 32-bit integer for great justice.

I work with a FORTRAN program where lots of string identifiers are 4 characters because of this. The number one requested feature is to be able to have id's longer than 4 characters. It will take a massive overhaul to change them.

The1ManMoshPit posted:

Don't actually do this.

MrMoo
Sep 14, 2000

quote:

A 5 character null terminated string in C takes exactly 6 bytes of memory.

quote:

A 5 character string in C takes exactly 5 bytes of memory.

Developing with messaging systems you unfortunately learn that some people really do use non-null terminated strings.

Paniolo
Oct 9, 2007

Heads will roll.

Dijkstracula posted:

Also, don't forget that if you're just returning string literals, you can just return a pointer to that literal as much as you want, with no memory overhead beyond the initial declaration.

Also also, come on, son:

No you pedantic gently caress a 5 character array takes 5 bytes of memory. Don't quote me and then edit what I said and then correct your own edit. If I had wanted to say string instead of array I'd have said so.

Paniolo fucked around with this message at 09:05 on Jul 5, 2010

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.
Sounds like it's nap time in the C/C++ thread!

ctz
Feb 6, 2003
while we're being pedantics, C's char type cannot store a character. depending on encoding, a character may need up to 4 bytes (using common encodings). so how about :

'A 5 character array in C takes between 5 and 20 bytes of memory.'

Null Pointer
May 20, 2004

Oh no!

ctz posted:

while we're being pedantics, C's char type cannot store a character. depending on encoding, a character may need up to 4 bytes (using common encodings). so how about :

'A 5 character array in C takes between 5 and 20 bytes of memory.'

Some codepoints are just diacritics. It may take many more bytes than that.

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"

Null Pointer posted:

Some codepoints are just diacritics. It may take many more bytes than that.

And some are ligatures so it could be less!

Let's end this once and for all: An n character array, where n > 0, takes up between 1 and ∞ bytes of memory.

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.
And this is why we should just call them chars.

shrughes
Oct 11, 2008

(call/cc call/cc)

Mustach posted:

And this is why we should just call them chars.

You mean cars.

POKEMAN SAM
Jul 8, 2004

shrughes posted:

You mean cars.

Char, so char star rhymes (and sounds awesome)

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.

shrughes posted:

You mean cars.
Not without Ric Ocasek.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I know there's precision() for setting the precision of a stream, but is there a way to force it to report that amount of decimal places whether it needs them or not? I'm thinking of the stream equivalent of the "%.04d" sequence for printf and friends. I'm inclined to use the stringstreams with sprintf or something similar actually because I can't find anything that will add the zeroes.

POKEMAN SAM
Jul 8, 2004

Rocko Bonaparte posted:

I know there's precision() for setting the precision of a stream, but is there a way to force it to report that amount of decimal places whether it needs them or not? I'm thinking of the stream equivalent of the "%.04d" sequence for printf and friends. I'm inclined to use the stringstreams with sprintf or something similar actually because I can't find anything that will add the zeroes.

Honestly, I'd just never use streams. At all.

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"

Rocko Bonaparte posted:

I know there's precision() for setting the precision of a stream, but is there a way to force it to report that amount of decimal places whether it needs them or not? I'm thinking of the stream equivalent of the "%.04d" sequence for printf and friends. I'm inclined to use the stringstreams with sprintf or something similar actually because I can't find anything that will add the zeroes.

code:
int main()
{
        double x = 3.14;

        cout << fixed << setprecision(5) << x << endl;

        return 0;
}
code:
$ ./a.out
3.14000

litghost
May 26, 2004
Builder

Rocko Bonaparte posted:

I know there's precision() for setting the precision of a stream, but is there a way to force it to report that amount of decimal places whether it needs them or not? I'm thinking of the stream equivalent of the "%.04d" sequence for printf and friends. I'm inclined to use the stringstreams with sprintf or something similar actually because I can't find anything that will add the zeroes.

If you're not adverse to boost, use the boost::format library. You can get the type safety of avoiding the printf-family of function but the convenience of printf-style format strings. It is compatible with stream objects.

code:
#include <boost/format.hpp>
#include <iostream>

int main(int argc, char *argv[])
{
        double x = 3.14;

        std::cout << boost::format("%.04f") % x << std::endl;

        return 0;
}

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip
Ugh at the overloading of the modulus operator, among other things

litghost
May 26, 2004
Builder

Otto Skorzeny posted:

Ugh at the overloading of the modulus operator, among other things

Agreed, but it is better than "fixed << setprecision(5)" in my opinion. Hopefully boost::format will get an overhaul once variadic templates are common.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

Flobbster posted:

code:
int main()
{
        double x = 3.14;

        cout << fixed << setprecision(5) << x << endl;

        return 0;
}
The problem comes around from having, say, 3.00. Then it would just show 3 without a decimal component.

I didn't know about boost::format. It looks like it mimics Python's format() command, with the way it overloads modulus.

Edit: Actually I just looked back at that and realized I experimented on that with a piece of code I wasn't running. Doh! It looks like << fixed << setprecision does work.

Rocko Bonaparte fucked around with this message at 03:48 on Jul 6, 2010

pseudorandom name
May 6, 2007

Maybe one day somebody will invent something nice using initialization lists and we can just do something like Format("{0} {2} {1}\n", {3, "stuff", 2.0f})

That Turkey Story
Mar 30, 2003

pseudorandom name posted:

Maybe one day somebody will invent something nice using initialization lists and we can just do something like Format("{0} {2} {1}\n", {3, "stuff", 2.0f})

Simple variadics are all you need for something like that, and even better, suffix operator overloading as well so that you can parse that 1st argument at compile time in order to verify the number of arguments/types that follow and give a compile-time error if there is a mismatch. You'd do this by making a suffix that yields a compile-time string which you could parse with a metafunction and then have your format template use SFINAE and/or static_assert.

Captain Frigate
Apr 30, 2007

you cant have it, you dont have nuff teef to chew it
Does anyone have experience with debugging CreateFile errors? I'm still working with Someone Else's Code (its supposed to do some networking thing that should be fairly simple) and I don't have enough experience to really know where to start looking. The function call itself is:
code:
SCom = CreateFile("\\\\.\\COM10", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 
It ends up returning INVALID_HANDLE_VALUE. I know that's not nearly enough to give meaningful advice, but I'm really not sure what to look for. Does anyone have any suggestions on where to start looking?

Adbot
ADBOT LOVES YOU

litghost
May 26, 2004
Builder

Captain Frigate posted:

Does anyone have experience with debugging CreateFile errors? I'm still working with Someone Else's Code (its supposed to do some networking thing that should be fairly simple) and I don't have enough experience to really know where to start looking. The function call itself is:
code:
SCom = CreateFile("\\\\.\\COM10", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 
It ends up returning INVALID_HANDLE_VALUE. I know that's not nearly enough to give meaningful advice, but I'm really not sure what to look for. Does anyone have any suggestions on where to start looking?

See GetLastError and this. Of course you would know this if you read CreateFile. So basically RTFM.

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