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
Spatial
Nov 15, 2007

hooah posted:

I'm just now running across char* objects, and am somewhat confused. The book says they're pointers, but unlike (all?) other pointers, you can assign a string directly to the pointer, rather than to the dereferenced object. Are char* objects different just because, or is there an explanation for this difference?
It's because string literals aren't objects, they're pointers to null-terminated arrays of char primitives.

String literals are little more than a quick way of telling the compiler, "Hey buddy, statically allocate this sequence of chars somewhere, I don't care where, and put a zero at the end while you're at it."

Adbot
ADBOT LOVES YOU

That Turkey Story
Mar 30, 2003

Spatial posted:

It's because string literals aren't objects, they're pointers to null-terminated arrays of char primitives.
The spergy pedant in me needs to point out that a string literal is an object. String literals are arrays of char const, not pointers (and a pointer is an object as well). You can assign string literals to char const* because all arrays allow you to implicitly create a pointer to the first element. In the case of string literals, you can also pull out a pointer to non-const char, for legacy reasons inherited from C, but you shouldn't be treating the data as non-const.

FamDav
Mar 29, 2008
what signifies an object?

ExcessBLarg!
Sep 1, 2001
The C FAQ has a whole section on Arrays and Pointers that pedantically and obsessively explains the difference between the two types. Honestly though, the most practical difference is how the sizeof operator works:
code:
#include <stdio.h>

const char foo[] = "This is a long string.";
const char *bar  = "This is a long string.";

int main(void) {
        printf("foo: %zu\nbar: %zu\n", sizeof(foo), sizeof(bar));
        return 0;
}
which yields on my AMD64 machine:
code:
foo: 23
bar: 8
For foo (of type "const char []"), sizeof returns the amount of memory allocated for the string itself (including null terminator), whereas for bar (of type "const char *"), sizeof returns the amount of memory allocated for the pointer, which is always 8 on this architecture.

There's an idiom you'll sometimes see in C code, "(sizeof(foo) / sizeof(foo[0]))" that returns the number of elements in an array. Of course, this only works for array types, not pointers. It's also worth pointing out that, unlike structs, arrays are not first-class types in C, and can't be passed directly into functions, so you must use a pointer here. This is why array types can always degrade to a pointer to its first element.

This also means that any function that takes an "array" (really, pointer to the array's first element) as a parameter needs some way to determine where the array ends, either by a second "count" parameter, or termininating the array with a sentinel.

FamDav
Mar 29, 2008
While you can't pass arrays by value (or even have an array be an argument without it auto-decaying to a pointer), you can use pointers/references to fixed size arrays and get some sweet type checking.

code:
void f( char (&x)[3] ) {}

int main()
{
	char x[2];
	char y[3];
	//f(x); // ERROR, incompatible type
	f(y);
}

Computer viking
May 30, 2011
Now with less breakage.

Ok, I did not know that.

b0lt
Apr 29, 2005

FamDav posted:

While you can't pass arrays by value (or even have an array be an argument without it auto-decaying to a pointer), you can use pointers/references to fixed size arrays and get some sweet type checking.

code:
void f( char (&x)[3] ) {}

int main()
{
	char x[2];
	char y[3];
	//f(x); // ERROR, incompatible type
	f(y);
}

Also a (dumb) C99 feature:

C code:
void f(char x[static 3]) {}

int main()
{
        char x[2];
        char y[3];
        char z[4];
        f(x); // warning: array argument is too small; contains 2 elements, callee requires at least 3 [-Warray-bounds]
        f(y);
        f(z);
}

That Turkey Story
Mar 30, 2003

FamDav posted:

what signifies an object?

Objects are class types (which includes structs), unions, arrays, and scalar types. Scalar types are arithmetic types, enum types, and pointer types. Things that aren't object types are reference types, void types, function types, etc.

tractor fanatic
Sep 9, 2005

Pillbug
C++ code:
class base{
public:
    virtual int a_thing() = 0;

    int use_a_thing(){
        return a_thing() * 2;
    }
};

class der : public base{
    int count;
public:
    virtual int a_thing(){
        return count++;
    }
};

int main(){
    der d;
    d.use_a_thing();
}

If I were to call der::use_a_thing() in a tight inner loop, where the full definition would be visible to the compiler, would I need to worry about the virtual? Would the compiler (specifically MSVC) be able to inline the whole thing?

FamDav
Mar 29, 2008

tractor fanatic posted:

C++ code:
class base{
public:
    virtual int a_thing() = 0;

    int use_a_thing(){
        return a_thing() * 2;
    }
};

class der : public base{
    int count;
public:
    virtual int a_thing(){
        return count++;
    }
};

int main(){
    der d;
    d.use_a_thing();
}

If I were to call der::use_a_thing() in a tight inner loop, where the full definition would be visible to the compiler, would I need to worry about the virtual? Would the compiler (specifically MSVC) be able to inline the whole thing?

If the der being called is definitely a der and the compiler can infer that from the code, then the compiler would be able to inline it.

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!

tractor fanatic posted:

If I were to call der::use_a_thing() in a tight inner loop, where the full definition would be visible to the compiler, would I need to worry about the virtual? Would the compiler (specifically MSVC) be able to inline the whole thing?
I would compile it optimized then step through it in the assembly-debugger to see what it does.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Any reasonably competent compiler should be able to do this devirtualization just from memory analysis, since both the constructor call and virtual call site are exposed. However, if there are any difficult stores or opaque uses of the local between the construction and the virtual call, devirtualization might be blocked.

On one level this shouldn't be true, because the language makes various guarantees that basically amount to "you can't drop a non-X on top of an object of type X and still access it through the original name". These guarantees are supposed to make devirtualizing calls on local variables fairly easy. And most compilers do indeed take advantage of this by devirtualizing calls made directly on objects (as opposed to via a reference or pointer).

Unfortunately, the forwarding rules for this guarantee are really arcane, surprising, and poorly-specified to boot. It's bad enough that I've had multiple extended discussions about how we could exploit this (beyond syntactic-level devirtualization) in clang and never really come up with anything reasonable. So while I can't actually speak for MSVC, I'd be pretty surprised if they did anything extra here.

You could in theory get this by virtue of a generic optimization to subclass-specialize base::use_a_thing, but I don't think MSVC does that optimization (nor do any of the other major compilers).

slovach
Oct 6, 2005
Lennie Fuckin' Briscoe
Am I missing something or what. I'm trying to write a RGBA8888 to RGB565 conversion.

My test input is:
0xAAFF00FF
10101010111111110000000011111111

Well ok, I want to mask the most significant bits off, so I come up with
0x00F800F8
00000000111110000000000011111000

pixel = pixel & 0x00F800F8;

And I get
0x00C800C8
00000000110010000000000011001000


I expected 0x00F800F8... how did it end up like that?

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!

slovach posted:

I expected 0x00F800F8... how did it end up like that?
Probably by you doing something else in addition to what you describe. Post code?

slovach
Oct 6, 2005
Lennie Fuckin' Briscoe
God loving dammit I actually had a typo I kept glancing over.

I missed it like 5 times and didn't catch it until just now. Oops.

:suicide:

OctaviusBeaver
Apr 30, 2009

Say what now?
I have a really basic conceptual question.

In this snippet:
code:
    int testing[3];
    testing[1] = 11;
    int *ptr;
    ptr = &testing[0];
    printf("%d\n",*(ptr+1)); //outputs 5
    printf("%d\n",*(ptr+sizeof(int)));
why does the (ptr + sizeof(int)) printf spit out garbage while the printf for (ptr+1) doesn't? Since I have an array of integers, which on my machine are size 4, shouldn't I have to skip ahead 4 memory addresses to reach the second element of the array? Why does that fail while my (ptr+1) skipping ahead 1 memory address works?

Paul MaudDib
May 3, 2006

TEAM NVIDIA:
FORUM POLICE
I basically have some code that iterates data, and several different simple payload functions that I want executed on them. I don't want to switch operations midstream, and I also don't want the overhead of making a function call. I basically just want to stick each payload into the function, compile it in turn, and give it a defined name, but without having the redundancy of the same iteration code being everywhere if I just copied and pasted five times.

So basically I want:
code:
void iterate_function(int * data, inline int func(int), int n);

inline int payload_a(int);

void deploy_payload_a(int * data, int n)
{
  iterate_function(data, payload_a, n);
}
How can I make that happen?

e: Perhaps prototype the payload and iteration functions, and then #define the deploy function? Would that inline it properly?

Paul MaudDib fucked around with this message at 02:37 on Jul 10, 2013

That Turkey Story
Mar 30, 2003

OctaviusBeaver posted:

I have a really basic conceptual question.

In this snippet:
code:
    int testing[3];
    testing[1] = 11;
    int *ptr;
    ptr = &testing[0];
    printf("%d\n",*(ptr+1)); //outputs 5
    printf("%d\n",*(ptr+sizeof(int)));
why does the (ptr + sizeof(int)) printf spit out garbage while the printf for (ptr+1) doesn't? Since I have an array of integers, which on my machine are size 4, shouldn't I have to skip ahead 4 memory addresses to reach the second element of the array? Why does that fail while my (ptr+1) skipping ahead 1 memory address works?

The integer that you add to a pointer is always implicitly in units equal to the size of the pointed-to type. In other words, adding 1 to the pointer in your example moves by sizeof(int) bytes. Adding sizeof(int) increments by sizeof(int) * sizeof(int) bytes.

OctaviusBeaver
Apr 30, 2009

Say what now?

That Turkey Story posted:

The integer that you add to a pointer is always implicitly in units equal to the size of the pointed-to type. In other words, adding 1 to the pointer in your example moves by sizeof(int) bytes. Adding sizeof(int) increments by sizeof(int) * sizeof(int) bytes.

Ah, gotcha that makes sense. Thanks!

Deffon
Mar 28, 2010

Paul MaudDib posted:

I basically have some code that iterates data, and several different simple payload functions that I want executed on them. I don't want to switch operations midstream, and I also don't want the overhead of making a function call. I basically just want to stick each payload into the function, compile it in turn, and give it a defined name, but without having the redundancy of the same iteration code being everywhere if I just copied and pasted five times.

So basically I want:
code:
void iterate_function(int * data, inline int func(int), int n);

inline int payload_a(int);

void deploy_payload_a(int * data, int n)
{
  iterate_function(data, payload_a, n);
}
How can I make that happen?

e: Perhaps prototype the payload and iteration functions, and then #define the deploy function? Would that inline it properly?
You need to inline iterate_function. As long as your payload functions are short and your not short on memory, this shouldn't be a problem.

Example:
code:
//iterate_function.h
inline void iterate_function(int * data, int (*func)(int), int n) {
	...
}

//payload_a.h
void deploy_payload_a(int * data, int n);

//payload.c
#include "iterate_function.h"

inline int payload_a(int) {
	...
}

void deploy_payload_a(int * data, int n) {
	iterate_function(data, payload_a, n);
}

Note that modern compilers are pretty smart about inlining, but if it refuses to inline your payload function on higher optimization levels, and it causes a bottleneck in your application, try a compiler specific extension (__attribute__((always_inline)) for gcc and __forceinline for msvc).

tractor fanatic
Sep 9, 2005

Pillbug
C++ code:
class some_type;

struct a_pair{
    some_type a, b;
};

a_pair array_of_pairs[16];

some_type * p = &array_of_pairs[0].a;
In practice, can I walk through all of the some_type in the array_of_pairs by iterating p, regardless of whether some_type is packed by compiler attributes? a_pair is not packed.

edit: probably not since an array of some_type would be unaligned so iterating a some_type* wouldn't work.

tractor fanatic fucked around with this message at 20:12 on Jul 10, 2013

b0lt
Apr 29, 2005

tractor fanatic posted:

C++ code:
class some_type;

struct a_pair{
    some_type a, b;
};

a_pair array_of_pairs[16];

some_type * p = &array_of_pairs[0].a;
In practice, can I walk through all of the some_type in the array_of_pairs by iterating p, regardless of whether some_type is packed by compiler attributes? a_pair is not packed.

edit: probably not since an array of some_type would be unaligned so iterating a some_type* wouldn't work.

Pretty much the only guarantees for struct memory layout you get are that &foo == &foo.a and &foo.a < &foo.b.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

tractor fanatic posted:

C++ code:

class some_type;

struct a_pair{
    some_type a, b;
};

a_pair array_of_pairs[16];

some_type * p = &array_of_pairs[0].a;

In practice, can I walk through all of the some_type in the array_of_pairs by iterating p, regardless of whether some_type is packed by compiler attributes? a_pair is not packed.

Formally, it is arguably not legal under the standards to get from one object to another with pointer arithmetic unless they're in an array. Even if you ignore that, the specific assumption that the pointer past the end of a field points to the next field is not strictly guaranteed to be portable, even if they have the same size and alignment.

But in practice, yes, you are not going to have any problems, regardless of what packed attributes you might have on what. (Except for the standard thing that forming a pointer to a member of a packed structure can leave you with an inadequately-aligned pointer.)

Dren
Jan 5, 2001

Pillbug
This might get sent me straight to the coding horrors thread but does goto'ing out of an exception block to some common error logging then rethrowing work?

Posting Principle
Dec 10, 2011

by Ralp
Is there a reason you can't just call a common error logging function?

Dren
Jan 5, 2001

Pillbug

Jerry SanDisky posted:

Is there a reason you can't just call a common error logging function?

I could. It's just poorly structured code in a terrible object model and I probably shouldn't have even asked the question because if I were to suggest a fix other than a rework of the object model it'd just be piling a horror on top of another horror.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Dren posted:

This might get sent me straight to the coding horrors thread but does goto'ing out of an exception block to some common error logging then rethrowing work?

No. Operand-less throw rethrows the (latest) exception currently being handled. If you leave the catch handler for an exception without rethrowing it, the exception is no longer being handled and is destroyed.

Posting Principle
Dec 10, 2011

by Ralp

rjmccall posted:

No. Operand-less throw rethrows the (latest) exception currently being handled. If you leave the catch handler for an exception without rethrowing it, the exception is no longer being handled and is destroyed.

Unrelated to the above question, but I was under the impression that you can have an exception live past the catch by getting an exception_ptr to it via std::current_exception. Is that the case?

Posting Principle fucked around with this message at 21:02 on Jul 11, 2013

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Jerry SanDisky posted:

Unrelated to the above question, but I was under the impression that you can have an exception live past the catch by getting an exception_ptr to it via std::current_exception. Is that the case?

I was glossing over that intentionally, but yes, C++11 lets you capture exceptions, pass them around outside of the exception mechanism, and throw them on multiple threads. Although some of the behavior, like whether and how often the exception is copied, is hilariously unportable, which I consider my greatest achievement in the committee process.

Dren
Jan 5, 2001

Pillbug

rjmccall posted:

No. Operand-less throw rethrows the (latest) exception currently being handled. If you leave the catch handler for an exception without rethrowing it, the exception is no longer being handled and is destroyed.

Thanks for the answer, I wasn't sure if goto would count as leaving.

Doctor w-rw-rw-
Jun 24, 2008
Diving into C++ since I figure it's about drat time I finally learn it. Is CMake an okay build system?

More generally, any tips for how to write and run code effectively? I'm thinking of using Vim with YouCompleteMe (which is a module that uses LLVM to do completions), but I have no beef with Eclipse. I'm on a mac, so Visual Studio is out.

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

Doctor w-rw-rw- posted:

Diving into C++ since I figure it's about drat time I finally learn it. Is CMake an okay build system?

More generally, any tips for how to write and run code effectively? I'm thinking of using Vim with YouCompleteMe (which is a module that uses LLVM to do completions), but I have no beef with Eclipse. I'm on a mac, so Visual Studio is out.

Anything can work but I would recommend just using XCode - it's easy to set up and you don't have to wonder if the tool is working correctly. There is a learning curve to C++ and you probably don't want to throw "did I really set everything up correctly" questions on top of actual issues with the language.

Rottbott
Jul 27, 2006
DMC
Can XCode compile a file individually yet? I found it unusable due to that alone.

Hughlander
May 11, 2005

Doctor w-rw-rw- posted:

Diving into C++ since I figure it's about drat time I finally learn it. Is CMake an okay build system?

More generally, any tips for how to write and run code effectively? I'm thinking of using Vim with YouCompleteMe (which is a module that uses LLVM to do completions), but I have no beef with Eclipse. I'm on a mac, so Visual Studio is out.

You can just use XCode and keep the same process you've been using all along. We mix C/C++/Obj-C/Obj-C++ on our projects all the time.

evensevenone
May 12, 2001
Glass is a solid.
I love YCM but you have to like vim for it to be a remotely enjoyable tool.


Xcode can use standard Makefiles if you want to go that way; CMake can also generate XCode projects now. But I'm not sure I would bother with CMake unless I was doing a big project with lots of dependencies that had to be cross-platform. It's definitely an additional layer or complication, not abstraction.

netcat
Apr 29, 2008
I don't know how XCode is in recent versions but I have found the code completion and general navigation around in your source to be far superiour in Eclipse (for C++), despite it's other faults.

Doctor w-rw-rw-
Jun 24, 2008

Well, I hate the poo poo out of making Makefiles, and for the project I have in mind, I want to make something that I know will compile a static binary and run a server on Linux boxes. To that end, XCode probably won't add much over anything else with decent autocomplete, and I don't have an workflow for that which I'm particularly attached to.

Sounds like there's nothing horribly bad about CMake. I don't mind too much about writing project definition files, I'm doing it to learn so if it's the tool of choice for writing big, cross-platform projects with lots of dependencies, that's worth the trouble to me. Also, I like vim, so I got that covered.

---

So about the language itself - assuming familiarity with most languages, what are the things fairly unique or uncommon in C++ that I should read up on?

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
C++ is a big language. It's gigantic. There's more in the language and library than any other language in the world.

You cannot learn all the different features and styles of C++ if you casually play around with it.

If you don't know C, I recommend learning that first. C++ is a lot easier to take in once you know C.

That Turkey Story
Mar 30, 2003

Doctor w-rw-rw- posted:

So about the language itself - assuming familiarity with most languages, what are the things fairly unique or uncommon in C++ that I should read up on?
In no particular order:

Constructors/destructors/RAII, templates (this is a huge one and includes lots and lots of things), unqualified name lookup, pointers, references, move-semantics, lambda functions, operator overloading, how to write exception-safe code, the standard libraries (and probably be at least a little familiar with the boost libraries). Probably more that I'm leaving out.

Adbot
ADBOT LOVES YOU

Doctor w-rw-rw-
Jun 24, 2008
I am aware of its humongousness, and am very comfortable with C. I just figure it's about time, since large or very interesting projects that need native-level speed are likely going to have to touch C++ sooner or later.

Cool, thanks!

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